美文网首页自定义控件
Bottom Sheets 底部动作条(或者底部纸片)

Bottom Sheets 底部动作条(或者底部纸片)

作者: 难得糊涂与君勉 | 来源:发表于2019-02-12 09:19 被阅读83次

Bottom Sheets 是一个从屏幕底部边缘向上滑出一个面板,使用这种方式向用户展示一组功能。
Google官方提供了在Design包中提供了三种实现方式:
(1)BottomSheetBehavior一种行为方式,需要配合CoordinatorLayout使用;
(2)BottomSheetDialog,一种方便的Dialog;
(3)BottomSheetDialogFragment,以一个Fragment为底部动作条;

BottomSheetBehavior

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="example.xlj.xljmdtest.MainActivity">

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

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="btn_bottom_sheetsdialogtest"
            android:text="测试BottomSheetsDialog完成底部动作条"
            />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="btn_bottom_sheetsialogtst_two"
            android:text="测试直接使用BottomSheetBehavior完成底部动作条"
            />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="btn_bottom_sheetsialogtst_three"
            android:text="测试Fragment的底部动作条"
            />

    </LinearLayout>


    <LinearLayout
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:behavior_hideable="true"
        app:behavior_peekHeight="50dp"
        app:layout_behavior="@string/bottom_sheet_behavior"
        android:background="#8adea9"
        >

        <!--app:behavior_hideable是保证能不能滑动到出去的关键,因为此View支持用户滑动,如果为false,那么用户下滑的时候,
不能完全将此View,完全滑出屏幕外。
-->
        <!--app:behavior_peekHeight是表示初始展示的大小,就是这个View初始展示在用户屏幕上多少,如果为0,则不可见了。-->


        <TextView
            android:layout_width="wrap_content"
            android:layout_height="48dp"
            android:layout_marginStart="40dp"
            android:layout_marginTop="8dp"
            android:text="第一条数据"
            />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="48dp"
            android:layout_marginStart="40dp"
            android:text="第二条数据"
            />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="48dp"
            android:layout_marginStart="40dp"
            android:text="第三条数据"
            />

    </LinearLayout>


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

关键点是:将需要作为底部进度条的<LinearLayout>直接作为CoordinatorLayout的子布局,并且给其加上
app:behavior_behavior="@string/bottom_sheet_behavior"

在代码方面,也需要做一些配合:

  //此方法是上面布局文件中第二个Button方法的具体实现
   public void btn_bottom_sheetsialogtst_two(View view) {
        //找到作为底部进度条的View
        BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.layout));
        //点击的时候,根据状态进行控制进度条
        if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED){
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
        }else {
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            /**
             * Caused by: java.lang.IllegalArgumentException: The view is not a child of CoordinatorLayout
             * 如果根布局不是CoordinatorLayout就会出现此异常,程序崩溃
             */

            /**
             * 程序有一个问题,就是,如果嵌套Scrollview的话,ScrollView容易失去焦点,通过尝试Fragfment的也一样,
               也会存在了滑动冲突的问题。此问题是用户往上翻界面的时候,默认的获取的是Bottom Sheet 的焦点,而不是ScrollView的焦点。
             */
        }
    }

下面是效果图:


结果

效果说明:
(1)底部动作条默认展示在用户界面上的区域是由peekHeight决定,默认是60dp
(2)为什么可以滑满全屏?是因为底部进度条部分的View代码,哪里的View的高度是match_parent。
(3)状态说明:

STATE_COLLAPSED: 默认的折叠状态, bottom sheets只在底部显示一部分布局。显示高度可以通过 app:behavior_peekHeight 设置,默认是

STATE_DRAGGING : 过渡状态,此时用户正在向上或者向下拖动bottom sheet

STATE_SETTLING: 视图从脱离手指自由滑动到最终停下的这一小段时间

STATE_EXPANDED: bottom sheet 处于完全展开的状态:当bottom sheet的高度低于CoordinatorLayout容器时,整个bottom sheet都可见;
或者CoordinatorLayout容器已经被bottom sheet填满。

STATE_HIDDEN : 默认无此状态(可通过app:behavior_hideable 启用此状态),启用后用户将能通过向下滑动完全隐藏 bottom sheet

此部分解释参考的文章
(4)其还提供了一个监听方法如下:

   bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                 //比如可以在里面完成不同状态下不同操作。
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {

            }
        });

官方参考查看其它API

BottomSheetDialog

直接在代码中使用:

  public void btn_bottom_sheetsdialogtest(View view) {
        BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(MainActivity.this);
        bottomSheetDialog.setCancelable(true);
        bottomSheetDialog.setContentView(R.layout.dialog_test);
        bottomSheetDialog.show();
    }

下面是这个Dialog的内容布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="300dp">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:layout_marginStart="40dp"
                android:layout_marginTop="8dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第一条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第二条数据"
                />

            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第三条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第四条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第五条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第三条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第四条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第五条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第三条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第四条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第五条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第三条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第四条数据"
                />
            <TextView
                android:layout_marginStart="40dp"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:text="第五条数据"
                />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

效果演示图:


ss.gif

几点说明:
(1)为啥不能铺满全屏,因为自己给这个LinearLayout设置的是300dp,如果是match_parent,用户在点击展示出Bottom Sheet Dialog效果如下:


ssw.gif

BottomSheetFragment的使用

(1)首先写一个Fragment继承BottomSheetDialogFragment

public class BottomSheetMyFragment extends BottomSheetDialogFragment {
   @Nullable
   @Override
   public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
       View v = inflater.inflate(R.layout.bottom_sheets_fragment, container, false);
       return v;
   }
}

其中Fragment的布局样式:

<?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="wrap_content"
        android:layout_height="48dp"
        android:layout_marginStart="40dp"
        android:layout_marginTop="8dp"
        android:text="第一条数据"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_marginStart="40dp"
        android:layout_marginTop="8dp"
        android:text="第一条数据"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_marginStart="40dp"
        android:layout_marginTop="8dp"
        android:text="第一条数据"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_marginStart="40dp"
        android:layout_marginTop="8dp"
        android:text="第一条数据"
        />


</LinearLayout>


一般的布局,想展示成什么样,就弄成什么样子的布局
在代码中调用:

public void btn_bottom_sheetsialogtst_three(View view) {
        new BottomSheetMyFragment().show(getSupportFragmentManager(),"dialog");
    }
45.gif

说明:
(1)BottomSheetFragment与BottomSheetDialog有一个共同点,就是你布局设置为match_parent,
如果你放置的内容小于16:9中(屏幕十六分之九),那么就展示内容的大小。如果大于16:9(屏幕十六分之九),就展示出屏幕十六分之九,多余部分,用户可以向上滑动展示出来。

相关文章

网友评论

    本文标题:Bottom Sheets 底部动作条(或者底部纸片)

    本文链接:https://www.haomeiwen.com/subject/thafjftx.html