【Android】BottomSheetDialog詳解

分類:編程 時間:2017-02-15

1.簡介

BottomSheetDialog是一個自定義的從底部滑入的對話框。市面上很多App都有類似的效果,今天我們實現如下效果:

這裏寫圖片描述

2.頁面布局

從底部彈出view的效果是BottomSheetBehavior來實現的。view必須支持嵌套滾動,而且必須是CoordinatorLayout的直接子類,來看下主題布局。

<?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:id="@+id/activity_bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitssystemWindows="true"
    app:behavior_hideable="true"
    >

    <!--Toolbar-->
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Light">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </android.support.design.widget.AppBarLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/tab_layout"
        android:gravity="center"
        android:orientation="vertical"
        app:behavior_hideable="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        >
        <Button
            android:text="顯示"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:id="@+id/btn_show"
            />

        <Button
            android:text="底部按鈕"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:id="@+id/btn_bottom" />
    </LinearLayout>

    <!--底部彈出框-->
    <LinearLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="?actionBarSize"
        android:layout_alignParentBottom="true"
        android:background="@android:color/holo_purple"
        app:behavior_hideable="true"
        app:behavior_peekHeight="0dp"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="首頁" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="課程" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="我的" />

    </LinearLayout>

</android.support.design.widget.CoordinatorLayout>

3.點擊按鈕彈出BottomSheetDialog

創建BottomSheetDialog以及相關的初始化:

        WindowManager wm = this.getWindowManager();
        int height = wm.getDefaultDisplay().getHeight();

        //構造函數的第二個參數可以設置BottomSheetDialog的主題樣式
//        mBottomSheetDialog = new BottomSheetDialog(this,R.style.MyBottomDialog);
        mBottomSheetDialog = new BottomSheetDialog(this);
        //導入底部reycler布局
        View view = LayoutInflater.from(this).inflate(R.layout.recycler_view, null, false);
        mBottomSheetDialog.setContentView(view);

        BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) view.getParent());
        //設置默認彈出高度為屏幕的0.4倍
        mBehavior.setPeekHeight((int) (0.4 * height));

        //設置點擊dialog外部不消失
        mBottomSheetDialog.setCanceledOnTouchOutside(false);

        //RecyclerView相關設置
        RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(new MyRecyclerAdapter(this));

點擊按鈕後,控制顯示和隱藏:

if (!mBottomSheetDialog.isShowing()) {
     mBottomSheetDialog.show();
} else {
     mBottomSheetDialog.dismiss();
}

此時點擊按鈕,如下效果:

這裏寫圖片描述

問題:此時再次點擊顯示按鈕的話,不會彈出底部框,屏幕會變暗,這是之前我們劃下收縮隱藏BottomSheetDialog後,bottomSheetDialogBehavior的狀態為隱藏,再次show之後,系統未恢復bottomSheetDialogBehavior的狀態,還是隱藏,所以再次點擊後頁面只是變暗,可以在隱藏時通過設置BottomSheetDialog的狀態來解決:

final BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(view);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);

4.彈出普通的View

我們點擊顯示底部按鈕時彈出如下界面:

這裏寫圖片描述

看下布局文件,CoordinatorLayout裏放了一個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:id="@+id/activity_bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    app:behavior_hideable="true"
    >
    <!--底部彈出框-->
    <LinearLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="?actionBarSize"
        android:layout_alignParentBottom="true"
        android:background="@android:color/holo_purple"
        app:behavior_hideable="true"
        app:behavior_peekHeight="0dp"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="首頁" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="課程" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="我的" />

    </LinearLayout>

</android.support.design.widget.CoordinatorLayout>

通過設置LinearLayout的app:layout_behavior屬性來設置此布局的行為,設置後Linear會在屏幕的底部:

app:layout_behavior="@string/bottom_sheet_behavior"

控制顯示和隱藏:

// 拿到這個tab_layout對應的BottomSheetBehavior
mBottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.tab_layout));
// 控制展開還是關閉
if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
    mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
    mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}

5.解決彈出dialog後Android5.0+status bar變黑

自定義BottomSheetDialog,屏幕高度減去狀態欄的高度即可:

public class MyBottomSheetDialog extends BottomSheetDialog{

    private Activity activity;

    public MyBottomSheetDialog(@NonNull Context context,Activity activity) {
        super(context);
        this.activity = activity;
    }

    public MyBottomSheetDialog(@NonNull Context context, @StyleRes int theme,Activity activity) {
        super(context, theme);
        this.activity = activity;
    }

    protected MyBottomSheetDialog(@NonNull Context context, boolean cancelable, OnCancelListener cancelListener,Activity activity) {
        super(context, cancelable, cancelListener);
        this.activity = activity;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int screenHeight = getScreenHeight(activity);
        int statusBarHeight = getStatusBarHeight(getContext());
        int dialogHeight = screenHeight - statusBarHeight;
        getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, dialogHeight == 0 ? ViewGroup.LayoutParams.MATCH_PARENT : dialogHeight);
    }

    private static int getScreenHeight(Activity activity) {
        DisplayMetrics displaymetrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        return displaymetrics.heightPixels;
    }

    private static int getStatusBarHeight(Context context) {
        int statusBarHeight = 0;
        Resources res = context.getResources();
        int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = res.getDimensionPixelSize(resourceId);
        }
        return statusBarHeight;
    }
}

參考:

1.http://blog.csdn.net/maosidiaoxian/article/details/52288597

2.http://blog.csdn.net/yanzhenjie1003/article/details/51938425


源碼下載


Tags:

文章來源:


ads
ads

相關文章
ads

相關文章

ad