BottomSheet详解

关系

  1. BottomSheet不是真正存在的类,而是一种称呼,表示该种控件类型,参照Google翻译,本文如下称之为“底页”,就是从屏幕底部弹出的工具条。与之对应是BottomSheetBehavior的行为类,它须要附属某个控件使用。该行为性质包括:
    • 能够从底部弹出
    • 能够上下拖拽布局
    • 能够单击淡黑色遮罩隐藏/关闭
  2. BottomSheetDialog继承Dialog,是一种对话框,它是拥有BottomSheetBehavior行为的对话框,从而实现从底部弹出和上下拉伸的效果。
  3. BottomSheetDialogFragment是包含BottomSheetDialog的片断(Fragment),因此它能够同时利用Fragment的特色和BottomSheet这一交互效果。

BottomSheetBehavior

使用

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

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

  • NestedScrollView的子视图只能有一个。android

<?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

  • app:behavior_hideable:当咱们上下拖拽时,布局是否能够所有隐藏。若是设置为真,那么你向下滑完以后,布局会被隐藏起来,而后就滑不出来了。。。(除非你写了按钮之类的逻辑控制它的行为)因此要谨慎。
  • app:behavior_peekHeight:是当底页关闭的时候,底部咱们能看到的高度,默认是0不可见。

获取行为

在布局文件中声明以后,就能够在代码中获取行为了。ide

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

方法

行为的一些经常使用的方法。工具

方法名 用法示例 说明
setHideable setHideable(true) 对应app:behavior_hideable属性
setPeekHeight setPeekHeight(500) 对应app:behavior_peekHeight属性
setBottomSheetCallback / 设置监听回调
setState setState(BottomSheetBehavior.STATE_EXPANDED) 设置底页状态

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能够作一些动画
    }
});
复制代码

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

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

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

  • 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效果

参考

相关文章
相关标签/搜索