添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • BottomSheet 不是真正存在的类,而是一种称呼,表示该种控件类型,参照Google翻译,本文以下称之为“底页”,就是从屏幕底部弹出的工具条。与之对应是 BottomSheetBehavior 的行为类,它需要附属某个控件使用。该行为性质包括:
  • 可以从底部弹出
  • 可以上下拖拽布局
  • 可以单击淡黑色遮罩隐藏/关闭
  • BottomSheetDialog 继承 Dialog ,是一种对话框,它是拥有 BottomSheetBehavior 行为的对话框,从而实现从底部弹出和上下拉伸的效果。
  • BottomSheetDialogFragment 是包含 BottomSheetDialog 的片段( Fragment ),所以它可以同时利用 Fragment 的特点和 BottomSheet 这一交互效果。
  • BottomSheetBehavior

    在xml布局文件中与 CoordinatorLayout 配合使用。如下设置后, NestedScrollView 具有 BottomSheetBehavior 的性质,且一开始就显示在布局中,初始的显示高度为 peekHeight 值。背景没有淡黑色遮罩,可以上下拖拽。

    关键语句 app:layout_behavior="@string/bottom_sheet_behavior"

    NestedScrollView 的子视图只能有一个。

    <?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"
        android:fitsSystemWindows="true">
        <android.support.v4.widget.NestedScrollView
            android:id="@+id/bottom_sheet"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:behavior_hideable="true"
            app:behavior_peekHeight="50dp"
            app:layout_behavior="@string/bottom_sheet_behavior">
            <!--内部布局-->
        </android.support.v4.widget.NestedScrollView>
    </android.support.design.widget.CoordinatorLayout>
    复制代码

    上述代码中有两个属性值得注意。

  • app:behavior_hideable :当我们上下拖拽时,布局是否可以全部隐藏。如果设置为真,那么你向下滑完之后,布局会被隐藏起来,然后就滑不出来了。。。(除非你写了按钮之类的逻辑控制它的行为)所以要谨慎。
  • app:behavior_peekHeight :是当底页关闭的时候,底部我们能看到的高度,默认是0不可见。
  • 在布局文件中声明之后,就可以在代码中获取行为了。

    // 获取视图
    View = findViewById(R.id.bottom_sheet);
    // 获取行为
    BottomSheetBehavior behavior = BottomSheetBehavior.from(view);
    复制代码

    方法

    行为的一些常用的方法。

    BottomSheetCallback

    底页的监听回调事件。

    behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
    	@Override
        public void onStateChanged(@NonNull View bottomSheet, int newState)
            //监听BottomSheet状态的改变
    	@Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset)
            //监听拖拽中的回调,根据slideOffset可以做一些动画
    复制代码

    底页行为一共有五种状态。

    STATE_HIDDEN: 隐藏状态。默认是false,可通过 app:behavior_hideable 属性设置。

    STATE_COLLAPSED: 折叠关闭状态。可通过 app:behavior_peekHeight 来设置显示的高度,peekHeight默认是0。

    STATE_DRAGGING: 被拖拽状态

    STATE_SETTLING: 拖拽松开之后到达终点位置(collapsed or expanded)前的状态。

    STATE_EXPANDED: 完全展开的状态。

    BottomSheetDialog

    这是具有底页行为性质的对话框,不需要与 CoordinatorLayout 配合使用。弹出时,背景为出现一层淡黑色遮罩。需要相关逻辑控制它的弹出。

    使用——布局文件

    设计 BottomSheetDialog 内部的视图。Xml可以不用被 CoordinatorLayout 包裹,但是还是推荐实用推荐的滑动控件 NestedScrollView

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.NestedScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!-- 内部视图 -->
    </android.support.v4.widget.NestedScrollView>
    复制代码

    使用——代码文件

    使用上述的布局文件,假设名称为 layout_bsd 。可以获取行为实现自定义。要注意的是从视图的父视图( (View)view.getParent() )获取底页行为,否则会报错:

    The view is not a child of CoordinatorLayout.

    BottomSheetDialog dialog = new BottomSheetDialog(context);
    View view = getLayoutInflater.inflate(R.layout.layout_bsd, null);
    dialog.setContentView(view);
    // 获取行为,用于自定义
    BottomSheetBehavior behavior = BottomSheetBehavior.from((View)view.getParent());
    dialog.show();
    复制代码

    BottomSheetDialogFragment

    有两种用法。

  • 当作中装了一个底页对话框的 Fragment 。实际是与底页对话框的作用和使用方法是相同的。
  • 具有底页行为的 Fragment
  • 用法一——披着 Fragment 外衣的 BottomSheetDialog

    重写 BottomSheetDialogFragment 中的 onCreateDialog 方法。可以看到和上面 BottomSheetDialog 的代码是相同的。同样可以在中间获取行为用于自定义。要注意是子视图的扩充用到的是 View.inflate 的静态方法,否则会报错。

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
        BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
        View view = View.inflate(getContext(), R.layout.dialog_bottom_sheet, null);
        dialog.setContentView(view);
        mBehavior = BottomSheetBehavior.from((View) view.getParent());
        return dialog;
    复制代码

    用法二——真正的 Fragment

    重写 BottomSheetDialogFragment 中的 onCreateView 方法。代码与 Fragment 的常规写法相同。不过不好的一点是不容易获取行为。如果要强行获取行为的话,可以使用以下的代码。

    @Override
    public void onStart() {
    	super.onStart();
        Dialog dialog = getDialog();
        if (dialog != null) {
            View bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
            bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
        View view = getView();
        view.post(() -> {
            View parent = (View) view.getParent();
            CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
            CoordinatorLayout.Behavior behavior = params.getBehavior();
            BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
            bottomSheetBehavior.setPeekHeight(view.getMeasuredHeight());
            ((View)bottomSheet.getParent()).setBackgroundColor(Color.TRANSPARENT);
    复制代码

    但是如果这两个方法都重写了,那么以 onCreateView 里的视图为准, onCreateDialog 会被覆盖。

    扩展:通过设置style实现圆角样式

    如下设置好之后,在创建 BottomSheetDialog 时传入样式。

    BottomSheetDialog dialog = new BottomSheetDialog(context, R.style.BottomSheetDialog);
    复制代码
    <!--styles.xml文件-->
    <style name="BottomSheet" parent="Widget.Design.BottomSheet.Modal">
        <!--背景,顶部两个圆角-->
        <item name="android:background">@drawable/bg_bottom_sheet</item>
    </style>
    <style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <!--底部弹出条的样式(相当于背景)-->
        <item name="bottomSheetStyle">@style/BottomSheet</item>
        <!--状态栏颜色-->
        <item name="android:statusBarColor">@color/transparent</item>
        <!--导航条颜色-->
        <item name="android:navigationBarColor">@color/white</item>
    </style>
    <!--以下是@drawable/bg_bottom_sheet-->
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners
            android:topLeftRadius="16dp"
            android:topRightRadius="16dp">
        </corners>
        <solid android:color="@android:color/white"/>
        <padding android:top="16dp"
            android:left="8dp"
            android:right="8dp" />
    </shape>
    复制代码

    效果图

    BottomSheet、BottomSheetDialog使用详解

    StackOverflow

    Android
    私信