【Android】BottomSheet的使用

529 阅读5分钟

BottomSheet

BottomSheet的介绍?

看本文之前,我们得先了解一下什么是 BottomSheet,什么情况下我们会使用?

BottomSheet(底部弹窗/底部面板) 是 Android 提供的一种交互控件;

它以 从屏幕底部滑出的方式 展示内容,用户可以拖拽、点击操作,适合做 信息展示、菜单、操作列表 等;

举个很简单的例子,抖音评论区大概率就是使用BottomSheet;

BottomSheet的分类

大致可以分为两类,分别是:

  1. Persistent BottomSheet(嵌入式底部表单)

大家从名字上也可以看出来,嵌入式,顾名思义就是写在xml文件中的,通过 CoordinatorLayout + BottomSheetBehavior 实现;

我的理解就是写在布局中,只是决定了它拖出来的方式而已;

2. Modal BottomSheet(模态式底部表单)

表现形式:像一个对话框(Dialog)一样,从底部滑出,遮住上面的内容;弹出时,背景会有一层阴影,我们可以点击空白处或下滑来关闭(通过后续的设置);通过 BottomSheetDialogBottomSheetDialogFragment 实现;

适合不是那么复杂场景下的,而且交互灵活,生命周期和普通 Dialog/Fragment 一样,显示时才创建,关闭后就销毁;

Persistent BottomSheet

Behavior

大家可能知道的是Behavior要设置在CoordinatorLayout布局中;其实Behavior的作用是来协调CoordinatorLayout布局中的直接子view的交互行为,包括滑动拖拽等等,我们可以用来进行可折叠式标题栏的实现或者底部表单的实现;

CoordinatorLayout布局

一个可以协调子视图之间交互行为的布局容器,通过behavior的设置明确了如何交互,两者联合以到达预期效果;

BottomSheetBehavior的几种模式

为什么要学习它的几种模式?

因为BottomSheetBehavior因为xml中是写死的,我们必须通过代码的逻辑来达到实现我们想要的效果;那么学习几种模式,能帮助我们更好的理解和使用;

STATE_HIDDEN:隐藏

此时我们可以类比理解成View.INVISABLE,它仍在存在但是在屏幕以外而已;

image.png

STATE_COLLAPSED :折叠状态,一般是一种半屏形态;

image.png

STATE_EXPANDED:完全展开,完全展开的高度是可配置,默认即屏幕高度;

image.png

STATE_DRAGGING:拖拽状态,标识人为手势拖拽中(手指未离开屏幕);

STATE_SETTLING :视图从脱离手指自由滑动到最终停下的这一小段时间,与STATE_DRAGGING差异在于当前并没有手指在拖拽。主要表达两种场景:初始弹出时动画状态、手指手动拖拽释放后的滑动状态;

BottomSheetBehavior的使用

xml文件中,设置需要弹出的控件设置behavior

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="wrap_content">
        <Button
            android:layout_width="wrap_content"
            android:text="按钮一"
            android:id = "@+id/buttom"
            android:layout_height="100dp"
            android:layout_gravity="center">

        </Button>
        <Button
            android:layout_marginTop="100dp"
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="按钮二"
            android:layout_gravity="center">

        </Button>
        <Button
            android:layout_height="100dp"
            android:text="按钮"
            android:layout_width="wrap_content"
            android:layout_marginTop="50dp"
            android:layout_gravity="center">

        </Button>
    </LinearLayout>
   <LinearLayout
       android:id = "@+id/bottombehavior"
       app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
       android:layout_width="match_parent"
       android:background="#000000"
       app:behavior_skipCollapsed = "true"
       app:behavior_peekHeight = "100dp"
       app:behavior_fitToContents = "true"
       android:layout_height="100dp">
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Hello World!"
           app:layout_constraintBottom_toBottomOf="parent"
           app:layout_constraintEnd_toEndOf="parent"
           app:layout_constraintStart_toStartOf="parent"
           app:layout_constraintTop_toTopOf="parent" />
   </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

主要是通过 app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"来设置的;

我们还可以定义一些相关的属性:

app:behavior_skipCollapsed = "true":定义是否允许滑动到peekheight以下高度;true代表关闭

app:behavior_peekHeight = "100dp":定义折叠时的高度;

app:behavior_fitToContents = "true":定义会不会完全展开;

在主活动中这样设置:

Button button = findViewById(R.id.buttom);
View view = findViewById(R.id.bottombehavior);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(view);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if(bottomSheetBehavior.getState()== BottomSheetBehavior.STATE_HIDDEN){
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        }else{
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
        }
    }
});

先得到具有behavior属性的父布局view,然后通过BottomSheetBehavior.from(view)获得behavior的实例;可以动态实现我们想要的效果;

Modal BottomSheet

BottomSheetDialog的使用

我们首先定义一个简单的布局,此处省略,

        BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(this);
        bottomSheetDialog.setContentView(R.layout.ttt);
        bottomSheetDialog.setCanceledOnTouchOutside(true);
        View bottomSheetView = bottomSheetDialog.findViewById(R.id.tttt);
        BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheetView);
        behavior.setPeekHeight(500);
        Button button2 = findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //         显示 BottomSheetDialog
                bottomSheetDialog.show();
            }
        });

代码讲解部分:

  1. 创建好布局之后,我们看第一行代码new了一个对话框,那么怎么把布局和new好的对话框关联到一起呢?

bottomSheetDialog.setContentView(R.layout.ttt);通过这行代码,我们将布局设置进对话框的视图;、

  1. 对话框的一些属性,比如是否允许触碰对话框外部关闭?

bottomSheetDialog.setCanceledOnTouchOutside(true);

  1. 怎么设置对话框的高度?
        View bottomSheetView = bottomSheetDialog.findViewById(R.id.tttt);
        BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheetView);
        behavior.setPeekHeight(500);

跟behavior的逻辑相似,这里不做过多解释;

  1. 怎么显示视图?

show() dismiss()来分别控制视图的开启和关闭;

此外还有显示和关闭对话框的监听器;

BottomSheetDialogFragment

这个的话,从名字上来看包含碎片,所以它包括了碎片的生命周期;

使用如下:

根据碎片的使用,BottomSheetDialogFragment的使用是建立xml文件,然后新建一个类

oncreatedialog方法中,我们需要返回一个dialog,通常在这里我们设置一些是否可关闭的属性;但是如果和外观有关的比如高度,就不能在这里设置了;

public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
    BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(getContext());
    bottomSheetDialog.setCanceledOnTouchOutside(true);
    bottomSheetDialog.setCancelable(true);
    return bottomSheetDialog;
}

createview方法中;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    warningBottomdialogBinding = WarningBottomdialogBinding.inflate(inflater,container,false);
    return warningBottomdialogBinding.getRoot();
}

本次分享就到这里!