BottomSheetBehavior.java revision 98475d29e771d7b15e4a109b22f410c7c1cf33d7
1452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki/* 2452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * Copyright (C) 2015 The Android Open Source Project 3452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * 4452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * Licensed under the Apache License, Version 2.0 (the "License"); 5452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * you may not use this file except in compliance with the License. 6452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * You may obtain a copy of the License at 7452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * 8452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * http://www.apache.org/licenses/LICENSE-2.0 9452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * 10452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * Unless required by applicable law or agreed to in writing, software 11452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * distributed under the License is distributed on an "AS IS" BASIS, 12452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * See the License for the specific language governing permissions and 14452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * limitations under the License. 15452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 16452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 17452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakipackage android.support.design.widget; 18452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 19452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.content.Context; 20452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.content.res.TypedArray; 21452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.os.Parcel; 22452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.os.Parcelable; 23452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.support.annotation.IntDef; 24dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Arakiimport android.support.annotation.NonNull; 25452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.support.design.R; 26452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.support.v4.view.MotionEventCompat; 279aec720809a123c6193304730acf8b55d6ce5a7aYuichi Arakiimport android.support.v4.view.NestedScrollingChild; 28e3e7063749d095bba8743cad0aeb7164a567890dYuichi Arakiimport android.support.v4.view.VelocityTrackerCompat; 29452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.support.v4.view.ViewCompat; 30452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.support.v4.widget.ViewDragHelper; 31452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.util.AttributeSet; 32452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.view.MotionEvent; 33e3e7063749d095bba8743cad0aeb7164a567890dYuichi Arakiimport android.view.VelocityTracker; 34452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.view.View; 35e3e7063749d095bba8743cad0aeb7164a567890dYuichi Arakiimport android.view.ViewConfiguration; 36452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport android.view.ViewGroup; 37452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 38452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport java.lang.annotation.Retention; 39452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport java.lang.annotation.RetentionPolicy; 40452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakiimport java.lang.ref.WeakReference; 41452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 42452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 43452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki/** 44452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * An interaction behavior plugin for a child view of {@link CoordinatorLayout} to make it work as 45452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * a bottom sheet. 46452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 47452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Arakipublic class BottomSheetBehavior<V extends View> extends CoordinatorLayout.Behavior<V> { 48452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 49452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 504df3c15e330c2f9730d3aa712f57befec8536dffYuichi Araki * Callback for monitoring events about bottom sheets. 51f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki */ 524df3c15e330c2f9730d3aa712f57befec8536dffYuichi Araki public abstract static class BottomSheetCallback { 53f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 54f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki /** 55f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * Called when the bottom sheet changes its state. 56f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * 57dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki * @param bottomSheet The bottom sheet view. 58dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki * @param newState The new state. This will be one of {@link #STATE_DRAGGING}, 59dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki * {@link #STATE_SETTLING}, {@link #STATE_EXPANDED}, 60dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki * {@link #STATE_COLLAPSED}, or {@link #STATE_HIDDEN}. 61f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki */ 62dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki public abstract void onStateChanged(@NonNull View bottomSheet, @State int newState); 63f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 64f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki /** 65f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * Called when the bottom sheet is being dragged. 66f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * 67dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki * @param bottomSheet The bottom sheet view. 68f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * @param slideOffset The new offset of this bottom sheet within its range, from 0 to 1 69f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * when it is moving upward, and from 0 to -1 when it moving downward. 70f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki */ 71dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki public abstract void onSlide(@NonNull View bottomSheet, float slideOffset); 72f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 73f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 74f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki /** 75452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * The bottom sheet is dragging. 76452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 77452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public static final int STATE_DRAGGING = 1; 78452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 79452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 80452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * The bottom sheet is settling. 81452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 82452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public static final int STATE_SETTLING = 2; 83452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 84452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 85452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * The bottom sheet is expanded. 86452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 87452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public static final int STATE_EXPANDED = 3; 88452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 89452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 90452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * The bottom sheet is collapsed. 91452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 92452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public static final int STATE_COLLAPSED = 4; 93452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 94f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki /** 95f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * The bottom sheet is hidden. 96f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki */ 97f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki public static final int STATE_HIDDEN = 5; 98f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 99452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** @hide */ 100f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki @IntDef({STATE_EXPANDED, STATE_COLLAPSED, STATE_DRAGGING, STATE_SETTLING, STATE_HIDDEN}) 101452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Retention(RetentionPolicy.SOURCE) 102452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public @interface State {} 103452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 104f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki private static final float HIDE_THRESHOLD = 0.5f; 105f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 106f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki private static final float HIDE_FRICTION = 0.1f; 107f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 108e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki private float mMaximumVelocity; 109f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 110452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private int mPeekHeight; 111452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 112452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private int mMinOffset; 113452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 114452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private int mMaxOffset; 115452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 116f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki private boolean mHideable; 117f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 118452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @State 119452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private int mState = STATE_COLLAPSED; 120452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 121452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private ViewDragHelper mViewDragHelper; 122452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 123452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private boolean mIgnoreEvents; 124452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 125e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki private int mLastNestedScrollDy; 126e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki 12749a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki private boolean mNestedScrolled; 12849a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki 129452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private int mParentHeight; 130452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 131452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private WeakReference<V> mViewRef; 132452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 1339aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki private WeakReference<View> mNestedScrollingChildRef; 134f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 1359aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki private BottomSheetCallback mCallback; 136f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 137e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki private VelocityTracker mVelocityTracker; 138e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki 139e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki private int mActivePointerId; 140f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 1414eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki private int mInitialY; 1424eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki 143b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki private boolean mTouchingScrollingChild; 144b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki 145452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 146452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * Default constructor for instantiating BottomSheetBehaviors. 147452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 148452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public BottomSheetBehavior() { 149452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 150452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 151452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 152452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * Default constructor for inflating BottomSheetBehaviors from layout. 153452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * 154452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * @param context The {@link Context}. 155452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * @param attrs The {@link AttributeSet}. 156452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 157452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public BottomSheetBehavior(Context context, AttributeSet attrs) { 158452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki super(context, attrs); 159452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki TypedArray a = context.obtainStyledAttributes(attrs, 160452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki R.styleable.BottomSheetBehavior_Params); 161452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki setPeekHeight(a.getDimensionPixelSize( 162452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki R.styleable.BottomSheetBehavior_Params_behavior_peekHeight, 0)); 163f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki setHideable(a.getBoolean(R.styleable.BottomSheetBehavior_Params_behavior_hideable, false)); 164452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki a.recycle(); 165e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki ViewConfiguration configuration = ViewConfiguration.get(context); 166e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); 167452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 168452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 169452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 170452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public Parcelable onSaveInstanceState(CoordinatorLayout parent, V child) { 171452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return new SavedState(super.onSaveInstanceState(parent, child), mState); 172452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 173452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 174452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 175452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public void onRestoreInstanceState(CoordinatorLayout parent, V child, Parcelable state) { 176452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki SavedState ss = (SavedState) state; 177452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki super.onRestoreInstanceState(parent, child, ss.getSuperState()); 178452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki // Intermediate states are restored as collapsed state 179f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki if (ss.state == STATE_DRAGGING || ss.state == STATE_SETTLING) { 180452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mState = STATE_COLLAPSED; 181f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } else { 182f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki mState = ss.state; 183452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 184452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 185452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 186452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 187452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) { 188452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki // First let the parent lay it out 189f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki if (mState != STATE_DRAGGING && mState != STATE_SETTLING) { 190a61e9790be0dd792393448810277b25990fcadb8Yuichi Araki if (ViewCompat.getFitsSystemWindows(parent) && 191a61e9790be0dd792393448810277b25990fcadb8Yuichi Araki !ViewCompat.getFitsSystemWindows(child)) { 192a61e9790be0dd792393448810277b25990fcadb8Yuichi Araki ViewCompat.setFitsSystemWindows(child, true); 193a61e9790be0dd792393448810277b25990fcadb8Yuichi Araki } 194f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki parent.onLayoutChild(child, layoutDirection); 195f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 196452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki // Offset the bottom sheet 197452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mParentHeight = parent.getHeight(); 198452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mMinOffset = Math.max(0, mParentHeight - child.getHeight()); 1993bd9d18c5855600254e907d6668f2ec4d7fd1c51Yuichi Araki mMaxOffset = Math.max(mParentHeight - mPeekHeight, mMinOffset); 200452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (mState == STATE_EXPANDED) { 201452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki ViewCompat.offsetTopAndBottom(child, mMinOffset); 202f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } else if (mHideable && mState == STATE_HIDDEN) { 203f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki ViewCompat.offsetTopAndBottom(child, mParentHeight); 204f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } else if (mState == STATE_COLLAPSED) { 205452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki ViewCompat.offsetTopAndBottom(child, mMaxOffset); 206452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 207452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (mViewDragHelper == null) { 208452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mViewDragHelper = ViewDragHelper.create(parent, mDragCallback); 209452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 210452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mViewRef = new WeakReference<>(child); 2119aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki mNestedScrollingChildRef = new WeakReference<>(findScrollingChild(child)); 212452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return true; 213452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 214452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 215452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 216452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { 21717fc77f5ca7c91daeab2e110669d9baf9d1a8090Yuichi Araki if (!child.isShown()) { 21817fc77f5ca7c91daeab2e110669d9baf9d1a8090Yuichi Araki return false; 21917fc77f5ca7c91daeab2e110669d9baf9d1a8090Yuichi Araki } 220452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki int action = MotionEventCompat.getActionMasked(event); 221e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki // Record the velocity 222e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (action == MotionEvent.ACTION_DOWN) { 223e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki reset(); 224e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 225e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (mVelocityTracker == null) { 226e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mVelocityTracker = VelocityTracker.obtain(); 227e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 228e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mVelocityTracker.addMovement(event); 229452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki switch (action) { 230452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki case MotionEvent.ACTION_UP: 231452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki case MotionEvent.ACTION_CANCEL: 232b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki mTouchingScrollingChild = false; 233e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mActivePointerId = MotionEvent.INVALID_POINTER_ID; 234452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki // Reset the ignore flag 235452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (mIgnoreEvents) { 236452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mIgnoreEvents = false; 237452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return false; 238452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 239452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki break; 240452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki case MotionEvent.ACTION_DOWN: 2414eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki int initialX = (int) event.getX(); 2424eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki mInitialY = (int) event.getY(); 2439aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki View scroll = mNestedScrollingChildRef.get(); 2444eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki if (scroll != null && parent.isPointInChildBounds(scroll, initialX, mInitialY)) { 245e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mActivePointerId = event.getPointerId(event.getActionIndex()); 246b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki mTouchingScrollingChild = true; 2479aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } 248e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mIgnoreEvents = mActivePointerId == MotionEvent.INVALID_POINTER_ID && 2494eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki !parent.isPointInChildBounds(child, initialX, mInitialY); 250452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki break; 251452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 2524eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki if (!mIgnoreEvents && mViewDragHelper.shouldInterceptTouchEvent(event)) { 2534eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki return true; 2544eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki } 2554eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki // We have to handle cases that the ViewDragHelper does not capture the bottom sheet because 2564eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki // it is not the top most view of its parent. This is not necessary when the touch event is 2574eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki // happening over the scrolling content as nested scrolling logic handles that case. 2584eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki View scroll = mNestedScrollingChildRef.get(); 2594eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki return action == MotionEvent.ACTION_MOVE && scroll != null && 2604eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki !mIgnoreEvents && mState != STATE_DRAGGING && 2614eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki !parent.isPointInChildBounds(scroll, (int) event.getX(), (int) event.getY()) && 2624eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki Math.abs(mInitialY - event.getY()) > mViewDragHelper.getTouchSlop(); 263452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 264452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 265452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 266452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { 26717fc77f5ca7c91daeab2e110669d9baf9d1a8090Yuichi Araki if (!child.isShown()) { 26817fc77f5ca7c91daeab2e110669d9baf9d1a8090Yuichi Araki return false; 26917fc77f5ca7c91daeab2e110669d9baf9d1a8090Yuichi Araki } 270e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki int action = MotionEventCompat.getActionMasked(event); 271e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (mState == STATE_DRAGGING && action == MotionEvent.ACTION_DOWN) { 272e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki return true; 273e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 274452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mViewDragHelper.processTouchEvent(event); 275e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki // Record the velocity 276e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (action == MotionEvent.ACTION_DOWN) { 277e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki reset(); 278e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 279e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (mVelocityTracker == null) { 280e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mVelocityTracker = VelocityTracker.obtain(); 281e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 282e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mVelocityTracker.addMovement(event); 2834eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki // The ViewDragHelper tries to capture only the top-most View. We have to explicitly tell it 2844eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki // to capture the bottom sheet in case it is not captured and the touch slop is passed. 285912d40d353f5b6d0a4fa18740ca40aa4b25b0f9cYuichi Araki if (action == MotionEvent.ACTION_MOVE && !mIgnoreEvents) { 2864eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki if (Math.abs(mInitialY - event.getY()) > mViewDragHelper.getTouchSlop()) { 2874eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki mViewDragHelper.captureChildView(child, event.getPointerId(event.getActionIndex())); 2884eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki } 2894eb453c75e552a2e0231a93468d9597a4069286eYuichi Araki } 290452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return true; 291452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 292452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 293e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki @Override 294e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, 295e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki View directTargetChild, View target, int nestedScrollAxes) { 296e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mLastNestedScrollDy = 0; 29749a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki mNestedScrolled = false; 298e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; 299e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 300e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki 301e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki @Override 302e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, 303e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki int dy, int[] consumed) { 304e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki View scrollingChild = mNestedScrollingChildRef.get(); 305e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (target != scrollingChild) { 306e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki return; 307e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 308e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki int currentTop = child.getTop(); 309e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki int newTop = currentTop - dy; 310e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (dy > 0) { // Upward 311e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (newTop < mMinOffset) { 312e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki consumed[1] = currentTop - mMinOffset; 313e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki ViewCompat.offsetTopAndBottom(child, -consumed[1]); 314e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki setStateInternal(STATE_EXPANDED); 315e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } else { 316e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki consumed[1] = dy; 317e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki ViewCompat.offsetTopAndBottom(child, -dy); 318e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki setStateInternal(STATE_DRAGGING); 319e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 320e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } else if (dy < 0) { // Downward 321e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (!ViewCompat.canScrollVertically(target, -1)) { 322e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (newTop <= mMaxOffset || mHideable) { 323e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki consumed[1] = dy; 324e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki ViewCompat.offsetTopAndBottom(child, -dy); 325e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki setStateInternal(STATE_DRAGGING); 326e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } else { 327e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki consumed[1] = currentTop - mMaxOffset; 328e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki ViewCompat.offsetTopAndBottom(child, -consumed[1]); 329e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki setStateInternal(STATE_COLLAPSED); 330e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 331e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 332e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 333e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki dispatchOnSlide(child.getTop()); 334e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mLastNestedScrollDy = dy; 33549a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki mNestedScrolled = true; 336e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 337e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki 338e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki @Override 339e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { 340b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki if (child.getTop() == mMinOffset) { 341b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki setStateInternal(STATE_EXPANDED); 342b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki return; 343b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki } 344b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki if (target != mNestedScrollingChildRef.get() || !mNestedScrolled) { 345e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki return; 346e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 347e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki int top; 348e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki int targetState; 349e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (mLastNestedScrollDy > 0) { 350e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki top = mMinOffset; 351e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki targetState = STATE_EXPANDED; 352e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } else if (mHideable && shouldHide(child, getYVelocity())) { 353e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki top = mParentHeight; 354e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki targetState = STATE_HIDDEN; 35549a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki } else if (mLastNestedScrollDy == 0) { 35649a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki int currentTop = child.getTop(); 35749a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki if (Math.abs(currentTop - mMinOffset) < Math.abs(currentTop - mMaxOffset)) { 35849a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki top = mMinOffset; 35949a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki targetState = STATE_EXPANDED; 36049a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki } else { 36149a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki top = mMaxOffset; 36249a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki targetState = STATE_COLLAPSED; 36349a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki } 364e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } else { 365e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki top = mMaxOffset; 366e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki targetState = STATE_COLLAPSED; 367e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 368e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (mViewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) { 369e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki setStateInternal(STATE_SETTLING); 370e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki ViewCompat.postOnAnimation(child, new SettleRunnable(child, targetState)); 371e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } else { 372e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki setStateInternal(targetState); 373e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 37449a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki mNestedScrolled = false; 375e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 376e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki 377e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki @Override 378e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, 379e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki float velocityX, float velocityY) { 380e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki return target == mNestedScrollingChildRef.get() && 381e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki (mState != STATE_EXPANDED || 382e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki super.onNestedPreFling(coordinatorLayout, child, target, 383e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki velocityX, velocityY)); 384e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 385e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki 386452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 387452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * Sets the height of the bottom sheet when it is collapsed. 388452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * 389452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * @param peekHeight The height of the collapsed bottom sheet in pixels. 390452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * @attr ref android.support.design.R.styleable#BottomSheetBehavior_Params_behavior_peekHeight 391452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 392452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public final void setPeekHeight(int peekHeight) { 393452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mPeekHeight = Math.max(0, peekHeight); 394452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mMaxOffset = mParentHeight - peekHeight; 395452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 396452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 397452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 398452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * Gets the height of the bottom sheet when it is collapsed. 399452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * 400452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * @return The height of the collapsed bottom sheet. 401452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * @attr ref android.support.design.R.styleable#BottomSheetBehavior_Params_behavior_peekHeight 402452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 403452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public final int getPeekHeight() { 404452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return mPeekHeight; 405452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 406452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 407452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 408f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * Sets whether this bottom sheet can hide when it is swiped down. 409f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * 410f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * @param hideable {@code true} to make this bottom sheet hideable. 411f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * @attr ref android.support.design.R.styleable#BottomSheetBehavior_Params_behavior_hideable 412f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki */ 413f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki public void setHideable(boolean hideable) { 414f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki mHideable = hideable; 415f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 416f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 417f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki /** 418f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * Gets whether this bottom sheet can hide when it is swiped down. 419f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * 420f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * @return {@code true} if this bottom sheet can hide. 421f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * @attr ref android.support.design.R.styleable#BottomSheetBehavior_Params_behavior_hideable 422f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki */ 423f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki public boolean isHideable() { 424f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki return mHideable; 425f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 426f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 427f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki /** 4284df3c15e330c2f9730d3aa712f57befec8536dffYuichi Araki * Sets a callback to be notified of bottom sheet events. 429f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * 4304df3c15e330c2f9730d3aa712f57befec8536dffYuichi Araki * @param callback The callback to notify when bottom sheet events occur. 431f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki */ 4324df3c15e330c2f9730d3aa712f57befec8536dffYuichi Araki public void setBottomSheetCallback(BottomSheetCallback callback) { 4334df3c15e330c2f9730d3aa712f57befec8536dffYuichi Araki mCallback = callback; 434f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 435f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 436f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki /** 437452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * Sets the state of the bottom sheet. The bottom sheet will transition to that state with 438452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * animation. 439452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * 440f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * @param state One of {@link #STATE_COLLAPSED}, {@link #STATE_EXPANDED}, or 441f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki * {@link #STATE_HIDDEN}. 442452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 443452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public final void setState(@State int state) { 44498475d29e771d7b15e4a109b22f410c7c1cf33d7Taeho Kim if (mViewRef == null) { 44598475d29e771d7b15e4a109b22f410c7c1cf33d7Taeho Kim return; 44698475d29e771d7b15e4a109b22f410c7c1cf33d7Taeho Kim } 447452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki V child = mViewRef.get(); 448452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (child == null) { 449452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return; 450452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 451452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki int top; 452452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (state == STATE_COLLAPSED) { 453452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki top = mMaxOffset; 454452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } else if (state == STATE_EXPANDED) { 455452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki top = mMinOffset; 456f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } else if (mHideable && state == STATE_HIDDEN) { 457f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki top = mParentHeight; 458452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } else { 459452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki throw new IllegalArgumentException("Illegal state argument: " + state); 460452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 461452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki setStateInternal(STATE_SETTLING); 462452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (mViewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) { 463452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki ViewCompat.postOnAnimation(child, new SettleRunnable(child, state)); 464452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 465452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 466452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 467452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki /** 468452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * Gets the current state of the bottom sheet. 469452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * 470452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * @return One of {@link #STATE_EXPANDED}, {@link #STATE_COLLAPSED}, {@link #STATE_DRAGGING}, 471452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * and {@link #STATE_SETTLING}. 472452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 473452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @State 474452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public final int getState() { 475452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return mState; 476452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 477452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 478452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private void setStateInternal(@State int state) { 479452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (mState == state) { 480452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return; 481452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 482452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mState = state; 483dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki View bottomSheet = mViewRef.get(); 484dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki if (bottomSheet != null && mCallback != null) { 485dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki mCallback.onStateChanged(bottomSheet, state); 486f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 487f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 488f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 489e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki private void reset() { 490e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mActivePointerId = ViewDragHelper.INVALID_POINTER; 491e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (mVelocityTracker != null) { 492e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mVelocityTracker.recycle(); 493e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mVelocityTracker = null; 494e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 495e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 496e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki 497f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki private boolean shouldHide(View child, float yvel) { 498f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki if (child.getTop() < mMaxOffset) { 499f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki // It should not hide, but collapse. 500f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki return false; 501f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 502f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki final float newTop = child.getTop() + yvel * HIDE_FRICTION; 503f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki return Math.abs(newTop - mMaxOffset) / (float) mPeekHeight > HIDE_THRESHOLD; 504f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 505f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 5069aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki private View findScrollingChild(View view) { 5079aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki if (view instanceof NestedScrollingChild) { 5089aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki return view; 5099aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } 5109aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki if (view instanceof ViewGroup) { 5119aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki ViewGroup group = (ViewGroup) view; 5129aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki for (int i = 0, count = group.getChildCount(); i < count; i++) { 5139aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki View scrollingChild = findScrollingChild(group.getChildAt(i)); 5149aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki if (scrollingChild != null) { 5159aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki return scrollingChild; 5169aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } 5179aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } 5189aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } 5199aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki return null; 520452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 521452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 522e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki private float getYVelocity() { 523e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); 524e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki return VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId); 525e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 526e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki 527452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private final ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() { 528452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 529452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 530452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public boolean tryCaptureView(View child, int pointerId) { 531e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (mState == STATE_DRAGGING) { 532e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki return false; 533e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki } 534b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki if (mTouchingScrollingChild) { 535b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki return false; 536b1eb1357ec33343b7271a6d3876ac4af84e15510Yuichi Araki } 537e3e7063749d095bba8743cad0aeb7164a567890dYuichi Araki if (mState == STATE_EXPANDED && mActivePointerId == pointerId) { 5389aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki View scroll = mNestedScrollingChildRef.get(); 5399aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki if (scroll != null && ViewCompat.canScrollVertically(scroll, -1)) { 5409aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki // Let the content scroll up 5419aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki return false; 5429aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } 5439aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } 544f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki return mViewRef != null && mViewRef.get() == child; 545f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 546f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 547f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki @Override 548f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { 549f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki dispatchOnSlide(top); 550452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 551452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 552452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 553452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public void onViewDragStateChanged(int state) { 554452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (state == ViewDragHelper.STATE_DRAGGING) { 555452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki setStateInternal(STATE_DRAGGING); 556452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 557452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 558452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 559452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 560452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public void onViewReleased(View releasedChild, float xvel, float yvel) { 561452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki int top; 562452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @State int targetState; 563f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki if (yvel < 0) { // Moving up 564452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki top = mMinOffset; 565452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki targetState = STATE_EXPANDED; 566f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } else if (mHideable && shouldHide(releasedChild, yvel)) { 567f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki top = mParentHeight; 568f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki targetState = STATE_HIDDEN; 56949a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki } else if (yvel == 0.f) { 57049a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki int currentTop = releasedChild.getTop(); 57149a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki if (Math.abs(currentTop - mMinOffset) < Math.abs(currentTop - mMaxOffset)) { 57249a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki top = mMinOffset; 57349a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki targetState = STATE_EXPANDED; 57449a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki } else { 57549a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki top = mMaxOffset; 57649a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki targetState = STATE_COLLAPSED; 57749a5904a773a7cfac127c5938671ed078d8ec8f3Yuichi Araki } 578452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } else { 579452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki top = mMaxOffset; 580452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki targetState = STATE_COLLAPSED; 581452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 582452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (mViewDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top)) { 583f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki setStateInternal(STATE_SETTLING); 584452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki ViewCompat.postOnAnimation(releasedChild, 585452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki new SettleRunnable(releasedChild, targetState)); 586f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } else { 587f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki setStateInternal(targetState); 588452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 589452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 590452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 591452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 592452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public int clampViewPositionVertical(View child, int top, int dy) { 593f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki return MathUtils.constrain(top, mMinOffset, mHideable ? mParentHeight : mMaxOffset); 594452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 595452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 596452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 597452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public int clampViewPositionHorizontal(View child, int left, int dx) { 598452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return child.getLeft(); 599452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 600f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 6019aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki @Override 6029aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki public int getViewVerticalDragRange(View child) { 6039aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki if (mHideable) { 6049aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki return mParentHeight - mMinOffset; 6059aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } else { 6069aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki return mMaxOffset - mMinOffset; 6079aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } 6089aec720809a123c6193304730acf8b55d6ce5a7aYuichi Araki } 609452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki }; 610452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 611f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki private void dispatchOnSlide(int top) { 612dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki View bottomSheet = mViewRef.get(); 613dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki if (bottomSheet != null && mCallback != null) { 614f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki if (top > mMaxOffset) { 615dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki mCallback.onSlide(bottomSheet, (float) (mMaxOffset - top) / mPeekHeight); 616f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } else { 617dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki mCallback.onSlide(bottomSheet, 618dffd8d4be91b2e5e0ce66ad96867182db0c02fd0Yuichi Araki (float) (mMaxOffset - top) / ((mMaxOffset - mMinOffset))); 619f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 620f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 621f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki } 622f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki 623452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private class SettleRunnable implements Runnable { 624452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 625452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private final View mView; 626452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 627452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @State 628452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki private final int mTargetState; 629452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 630452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki SettleRunnable(View view, @State int targetState) { 631452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mView = view; 632452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki mTargetState = targetState; 633452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 634452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 635452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 636452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public void run() { 637452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (mViewDragHelper != null && mViewDragHelper.continueSettling(true)) { 638452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki ViewCompat.postOnAnimation(mView, this); 639452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } else { 640452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki setStateInternal(mTargetState); 641452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 642452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 643452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 644452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 645452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki protected static class SavedState extends View.BaseSavedState { 646452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 647452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @State 648452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki final int state; 649452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 650452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public SavedState(Parcel source) { 651452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki super(source); 652452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki //noinspection ResourceType 653452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki state = source.readInt(); 654452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 655452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 656452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public SavedState(Parcelable superState, @State int state) { 657452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki super(superState); 658452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki this.state = state; 659452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 660452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 661452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 662452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public void writeToParcel(Parcel out, int flags) { 663452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki super.writeToParcel(out, flags); 664452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki out.writeInt(state); 665452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 666452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 667452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public static final Parcelable.Creator<SavedState> CREATOR = 668452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki new Parcelable.Creator<SavedState>() { 669452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 670452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public SavedState createFromParcel(Parcel source) { 671452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return new SavedState(source); 672452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 673452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 674452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @Override 675452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public SavedState[] newArray(int size) { 676452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return new SavedState[size]; 677452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 678452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki }; 679452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 680452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 681f28a0f76c7a46d61785ef7cbc407c19942ecab46Yuichi Araki /** 682452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * A utility function to get the {@link BottomSheetBehavior} associated with the {@code view}. 683452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * 684452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * @param view The {@link View} with {@link BottomSheetBehavior}. 685452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki * @return The {@link BottomSheetBehavior} associated with the {@code view}. 686452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki */ 687452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki @SuppressWarnings("unchecked") 688452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki public static <V extends View> BottomSheetBehavior<V> from(V view) { 689452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki ViewGroup.LayoutParams params = view.getLayoutParams(); 690452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (!(params instanceof CoordinatorLayout.LayoutParams)) { 691452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki throw new IllegalArgumentException("The view is not a child of CoordinatorLayout"); 692452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 693452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params) 694452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki .getBehavior(); 695452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki if (!(behavior instanceof BottomSheetBehavior)) { 696452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki throw new IllegalArgumentException( 697452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki "The view is not associated with BottomSheetBehavior"); 698452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 699452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki return (BottomSheetBehavior<V>) behavior; 700452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki } 701452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki 702452f94d1c58e2a7476019b98c3bf0e4b322d1525Yuichi Araki} 703