【Android】BottomSheet的三种使用
BottomSheet
BottomSheet的介绍?
看本文之前,我们得先了解一下什么是 BottomSheet
,什么情况下我们会使用?
BottomSheet(底部弹窗/底部面板) 是 Android 提供的一种交互控件;
它以 从屏幕底部滑出的方式 展示内容,用户可以拖拽、点击操作,适合做 信息展示、菜单、操作列表 等;
举个很简单的例子,抖音评论区大概率就是使用BottomSheet
;
BottomSheet的分类
大致可以分为两类,分别是:
Persistent BottomSheet
(嵌入式底部表单)
大家从名字上也可以看出来,嵌入式,顾名思义就是写在xml文件中的,通过 CoordinatorLayout
+ BottomSheetBehavior
实现;
我的理解就是写在布局中,只是决定了它拖出来的方式而已;
2. Modal BottomSheet
(模态式底部表单)
表现形式:像一个对话框(Dialog
)一样,从底部滑出,遮住上面的内容;弹出时,背景会有一层阴影,我们可以点击空白处或下滑来关闭(通过后续的设置);通过 BottomSheetDialog
或 BottomSheetDialogFragment
实现;
适合不是那么复杂场景下的,而且交互灵活,生命周期和普通 Dialog
/Fragment
一样,显示时才创建,关闭后就销毁;
Persistent BottomSheet
Behavior
大家可能知道的是Behavior
要设置在CoordinatorLayout
布局中;其实Behavior
的作用是来协调CoordinatorLayout
布局中的直接子view
的交互行为,包括滑动拖拽等等,我们可以用来进行可折叠式标题栏的实现或者底部表单的实现;
CoordinatorLayout布局
一个可以协调子视图之间交互行为的布局容器,通过behavio
r的设置明确了如何交互,两者联合以到达预期效果;
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"><LinearLayoutandroid:layout_width="match_parent"android:orientation="vertical"android:layout_height="wrap_content"><Buttonandroid:layout_width="wrap_content"android:text="按钮一"android:id = "@+id/buttom"android:layout_height="100dp"android:layout_gravity="center"></Button><Buttonandroid:layout_marginTop="100dp"android:layout_width="wrap_content"android:layout_height="100dp"android:text="按钮二"android:layout_gravity="center"></Button><Buttonandroid:layout_height="100dp"android:text="按钮"android:layout_width="wrap_content"android:layout_marginTop="50dp"android:layout_gravity="center"></Button></LinearLayout><LinearLayoutandroid: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"><TextViewandroid: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() {@Overridepublic 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() {@Overridepublic void onClick(View view) {// 显示 BottomSheetDialogbottomSheetDialog.show();}});
代码讲解部分:
- 创建好布局之后,我们看第一行代码new了一个对话框,那么怎么把布局和new好的对话框关联到一起呢?
bottomSheetDialog.setContentView(R.layout.ttt);
通过这行代码,我们将布局设置进对话框的视图;、
- 对话框的一些属性,比如是否允许触碰对话框外部关闭?
bottomSheetDialog.setCanceledOnTouchOutside(true);
- 怎么设置对话框的高度?
View bottomSheetView = bottomSheetDialog.findViewById(R.id.tttt);BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(bottomSheetView);behavior.setPeekHeight(500);
跟behavior的逻辑相似,这里不做过多解释;
- 怎么显示视图?
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();
}
本次分享就到这里!