【Android】BottomSheet的三种使用 - 指南

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,它仍在存在但是在屏幕以外而已;

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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 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 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();
}

本次分享就到这里!

posted @ 2025-09-22 21:49  yfceshi  阅读(20)  评论(0)    收藏  举报