1. 程式人生 > >Android Design Support Library BottomSheetBehavior使用

Android Design Support Library BottomSheetBehavior使用

本文使用的 com.android.support:design 版本為 23.3.0

效果圖

gif

相關類

bottom_sheet

BottomSheetBehavior

此類類似一個工具類,並不能在佈局中使用,下面我們看看怎麼實現我們效果圖中的功能

layout

<FrameLayout
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation
="vertical" app:behavior_hideable="true" app:behavior_peekHeight="0dp" app:layout_behavior="@string/bottom_sheet_behavior">
<include layout="@layout/include_bottom_sheet_layout" /> </FrameLayout>

我們可以看到id = bottom_sheet 的FrameLayout設定了一些app名稱空間的屬性,其中app:layout_behavior="@string/bottom_sheet_behavior"

才是重點,設定這個才能與今天所講的類聯絡在一起,所以此View的parent view 必須是android.support.design.widget.CoordinatorLayout

include:include_bottom_sheet_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height
="match_parent" android:orientation="vertical">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="android.support.design-23.3.0" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="AppBarLayout" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="BottomSheetBehavior" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="BottomSheetDialog" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="BottomSheetDialogFragment" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="CircularBorderDrawable" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="CircularBorderDrawableLollipop" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="CollapsingTextHelper" android:textSize="20sp" /> </LinearLayout>

完整佈局

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.v7.widget.AppCompatButton
            android:id="@+id/btnBehavior"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="BottomSheetBehavior"
            android:textAllCaps="false" />

        <android.support.v7.widget.AppCompatButton
            android:id="@+id/btnDialog"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="BottomSheetDialog"
            android:textAllCaps="false" />
    </LinearLayout>


    <FrameLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:behavior_hideable="true"
        app:behavior_peekHeight="0dp"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <include layout="@layout/include_bottom_sheet_layout" />

    </FrameLayout>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email"
        app:borderWidth="0dp"
        app:elevation="5dp"
        app:layout_anchor="@id/bottom_sheet"
        app:layout_anchorGravity="right|top"
        app:pressedTranslationZ="10dp" />
</android.support.design.widget.CoordinatorLayout>

Java Code

View bottomSheet =  findViewById(R.id.bottom_sheet);
BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheet);

R.id.bottom_sheet是我們想要展示的View,這個時候BottomSheetBehavior就派上用場了,使用簡單,直接呼叫一個靜態方法 from() 方法搞定

int state = behavior.getState();
if (state == BottomSheetBehavior.STATE_EXPANDED) {
    behavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}else{
    behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}

當用戶觸發某一動作事件後,可採用這部分程式碼對View的顯示與隱藏。

好了,基本用法就這麼簡單,下面我們來看看BottomSheetBehavior類中有一些什麼方法值得我們關注

BottomSheetBehavior

BottomSheetBehavior

選中部分就是我們要了解學習的類與方法

BottomSheetCallback

/**
 * bottom sheets監控事件的回撥
 */
public abstract static class BottomSheetCallback {
    /**
     * 當bottom sheets狀態被改變回調
     * @param bottomSheet The bottom sheet view.
     * @param newState    改變後新的狀態
     */
    public abstract void onStateChanged(@NonNull View bottomSheet, @State int newState);
    /**
     * 當bottom sheets拖拽時回撥
     * @param bottomSheet The bottom sheet view.
     * @param slideOffset 滑動量;從0到1時向上移動
     */
    public abstract void onSlide(@NonNull View bottomSheet, float slideOffset);
}

Public Methods

方法 用途
setPeekHeight 偷看的高度;哈,這麼理解,就是預設顯示後View露頭的高度
getPeekHeight @see setPeekHeight()
setHideable 設定是否可以隱藏,如果為true,表示狀態可以為STATE_HIDDEN
isHideable @see setHideable()
setState 設定狀態;設定不同的狀態會影響BottomSheetView的顯示效果
getState 獲取狀態
setBottomSheetCallback 設定狀態改變回調

BottomSheetDialog

此類其實就是對BottomSheetBehavior的封裝,將我們的BottomSheetView改裝成一個Dialog顯示形式

用法

BottomSheetDialog bsDialog = new BottomSheetDialog(this);
bsDialog.setContentView(R.layout.include_bottom_sheet_layout);
bsDialog.show();

解析

private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) {
    final CoordinatorLayout coordinator = (CoordinatorLayout) View.inflate(getContext(),
            R.layout.design_bottom_sheet_dialog, null);
    if (layoutResId != 0 && view == null) {
        view = getLayoutInflater().inflate(layoutResId, coordinator, false);
    }
    FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(R.id.design_bottom_sheet);
    BottomSheetBehavior.from(bottomSheet).setBottomSheetCallback(mBottomSheetCallback);
    if (params == null) {
        bottomSheet.addView(view);
    } else {
        bottomSheet.addView(view, params);
    }
    // We treat the CoordinatorLayout as outside the dialog though it is technically inside
    if (shouldWindowCloseOnTouchOutside()) {
        coordinator.findViewById(R.id.touch_outside).setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (isShowing()) {
                            cancel();
                        }
                    }
                });
    }
    return coordinator;
}

此方法就是核心程式碼,主要作用就是將我們通過BottomSheetDialog.setContentView()方法設定的View通過BottomSheetBehavior.from(View)方法初始化一個BottomSheetBehavior物件

BottomSheetDialogFragment

此類其實就是對BottomSheetDialog的封裝,內部實現很簡單,我們看下實現程式碼:

public class BottomSheetDialogFragment extends AppCompatDialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new BottomSheetDialog(getActivity(), getTheme());
    }

}

以上是此類的全部程式碼,很簡單,繼承DialogFragment,重寫onCreateDialog方法,返回一個BottomSheetDialog例項

Demo程式碼github地址