一、效果图,不太清晰
本想一次全部录下来做成 gif 图,可惜高清 gif 图太大了,无法上传,只能换成普清模式,一次录一段,有更好的录制 gif 图的方法可以留言告知。现在只能勉强看看。
二、实现类似抖音拖拽评论框效果
首先布局的最外层要是CoordinatorLayout ,然后对话框的最外层要加上这三个属性:
app:behavior_hideable="true"app:behavior_peekHeight="50dp"app:layout_behavior="@string/bottom_sheet_behavior"
- app:behavior_hideable=”true” —-> 可选设置,是否支持隐藏,设置为 false 或是不设置就是不支持,就不能调用隐藏的方法setState(BottomSheetBehavior.STATE_HIDDEN)
- app:behavior_peekHeight=”50dp” —-> 必选设置,收起高度,上图中黄色区域
- app:layout_behavior 必选设置,设置以后才会有对话框效果
完整的界面布局:
<?xml version="1.0" encoding="utf-8"?><androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:app="http://schemas.android.com/apk/res-auto"><androidx.core.widget.NestedScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:id="@+id/btn_mddialog_bottomdialog"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="bottomSheetDialog"android:textAllCaps="false"/><Buttonandroid:id="@+id/btn_mddialog_bottomdialog2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="bottomSheetDialog"android:textAllCaps="false"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:id="@+id/btn_mddialog_list"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="bottomSheetDialog-list"android:textAllCaps="false"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><Buttonandroid:id="@+id/btn_mddialog_expande"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="底部对话框展开"android:textAllCaps="false"/><Buttonandroid:id="@+id/btn_mddialog_hide"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="底部对话框隐藏"android:textAllCaps="false"android:layout_marginStart="5dp"android:layout_marginEnd="5dp"/><Buttonandroid:id="@+id/btn_mddialog_collose"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="底部对话框关闭"android:textAllCaps="false"/></LinearLayout></LinearLayout></androidx.core.widget.NestedScrollView><!-- 底部可以拉出的对话框,仿抖音--><LinearLayoutandroid:id="@+id/ll_mddialog_bottom"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"app:behavior_hideable="false"app:behavior_peekHeight="50dp"app:layout_behavior="@string/bottom_sheet_behavior"android:background="@color/white"><TextViewandroid:id="@+id/tv_mddialog_bottomDialog"android:layout_width="match_parent"android:layout_height="50dp"android:text="拖拽可以拉出对话框"android:textColor="@color/white"android:gravity="center"android:background="@color/yellow_FF9B52"/><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_mddialog_bottom"android:layout_width="match_parent"android:layout_height="200dp"/></LinearLayout></androidx.coordinatorlayout.widget.CoordinatorLayout>
activity 部分:
class MdDialogActivity: AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_mddialog)//bottomdialog testbtn_mddialog_bottomdialog.setOnClickListener {showBottomDialog()}btn_mddialog_bottomdialog2.setOnClickListener {val dialog = SimpleDialog(this)dialog.show()}btn_mddialog_list.setOnClickListener {val dialog = ListDialog(this)dialog.show()}//把这个底部菜单和一个BottomSheetBehavior关联起来val behavior = BottomSheetBehavior.from(ll_mddialog_bottom)//底部对话框展开点击btn_mddialog_expande.setOnClickListener {if(behavior.state == BottomSheetBehavior.STATE_EXPANDED) {//展开不管return@setOnClickListener}else{behavior.setState(BottomSheetBehavior.STATE_EXPANDED)}}//底部对话框隐藏点击btn_mddialog_hide.setOnClickListener {behavior.setState(BottomSheetBehavior.STATE_HIDDEN)}//底部对话框关闭btn_mddialog_collose.setOnClickListener {behavior.setState(BottomSheetBehavior.STATE_COLLAPSED)}//初始化底部对话框列表initBottomList()// tv_mddialog_bottomDialog.setOnClickListener {// if(behavior.state == BottomSheetBehavior.STATE_EXPANDED) {//展开就隐藏// behavior.setState(BottomSheetBehavior.STATE_HIDDEN)// }else {//隐藏就展开// behavior.setState(BottomSheetBehavior.STATE_EXPANDED)// }// }}val list = arrayListOf<String>("测试数据一","测试数据二","测试数据三","测试数据四","测试数据一","测试数据二","测试数据三","测试数据四")val mAdapter by lazy { ListDialogAdapter() }private fun initBottomList() {rv_mddialog_bottom?.run {layoutManager = LinearLayoutManager(context)adapter = mAdapter}mAdapter.setList(list)}private fun showBottomDialog() {//可以滑动,向下滑动关闭val dialog = BottomSheetDialog(this)dialog.setCanceledOnTouchOutside(true)//设置点击空白处是否消失dialog.setCancelable(false)//设置是否可以滑动关闭val view = layoutInflater.inflate(R.layout.dialog_bottom_simple, null, false)dialog.setContentView(view)view.findViewById<TextView>(R.id.tv_dialog_bottom_simple_title).text = "第一条标签"dialog.show()}}
三、BottomSheetDialog 简单使用
3.1 简单对话框实现
setCancelable(false)//是否可以滑动关闭setCanceledOnTouchOutside(true)//是否可以点击外部关闭
效果图:
对话框实现类:
private fun showBottomDialog() {//可以滑动,向下滑动关闭val dialog = BottomSheetDialog(this)dialog.setCanceledOnTouchOutside(true)//设置点击空白处是否消失val view = layoutInflater.inflate(R.layout.dialog_bottom_simple, null, false)dialog.setContentView(view)view.findViewById<TextView>(R.id.tv_dialog_bottom_simple_title).text = "第一条标签"dialog.show()}
简单对话框布局:
<?xml version="1.0" encoding="utf-8"?><RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:background="@color/white"><TextViewandroid:id="@+id/tv_dialog_bottom_simple_title"android:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:text="设置备注及星标"android:gravity="center_vertical"android:paddingStart="@dimen/m10"/><TextViewandroid:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:text="设置备注及星标"android:gravity="center_vertical"android:paddingStart="@dimen/m10"/><TextViewandroid:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:text="设置备注及星标"android:gravity="center_vertical"android:paddingStart="@dimen/m10"/><TextViewandroid:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:text="设置备注及星标"android:gravity="center_vertical"android:paddingStart="@dimen/m10"/></LinearLayout></RelativeLayout>
3.2 简单对话框实现圆角背景
- 1.效果图

对话框类 ```kotlin class SimpleDialog(context: Context): BottomSheetDialog(context) {
init { setContentView(R.layout.dialog_bottom_simple_fillet) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) //布局内容动态设置 tv_dialog_bottom_simple_title.text = “第一个标签” }
}
- 3. 对话框布局```kotlin<?xml version="1.0" encoding="utf-8"?><RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:background="@drawable/bg_white_fillet_10"><TextViewandroid:id="@+id/tv_dialog_bottom_simple_title"android:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:text="设置备注及星标"android:gravity="center_vertical"android:paddingStart="@dimen/m10"/><TextViewandroid:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:text="设置备注及星标"android:gravity="center_vertical"android:paddingStart="@dimen/m10"/><TextViewandroid:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:text="设置备注及星标"android:gravity="center_vertical"android:paddingStart="@dimen/m10"/><TextViewandroid:layout_width="match_parent"android:layout_height="@dimen/dp_40"android:text="设置备注及星标"android:gravity="center_vertical"android:paddingStart="@dimen/m10"/></LinearLayout></RelativeLayout>
圆角背景
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="@color/white"/><corners android:topLeftRadius="@dimen/m10"android:topRightRadius="@dimen/m10"/></shape>
5.代码实现背景透明
btn_mddialog_bottomdialog2.setOnClickListener {val dialog = SimpleDialog(this)//dialog.window!!.setDimAmount(0f)//;设置窗体背景透明//设置背景透明,以便显示圆角背景dialog.window!!.findViewById<View>(R.id.design_bottom_sheet).setBackgroundColor(Color.TRANSPARENT)dialog.show()}
3.3 固定高度的 RecycelerView 对话框
对 RecyclerView 设置固定高度可以参考这个RecyclerView 设置固定数目 Item,这里简单做个示例,固定了高度,效果图如下:

对话框代码: ```kotlin class ListDialog(context: Context): BottomSheetDialog(context) { init {setContentView(R.layout.dialog_bottom)setCancelable(false)//是否可以滑动关闭setCanceledOnTouchOutside(true)//是否可以点击外部关闭
} val list = arrayListOf
(“测试数据一”,”测试数据二”,”测试数据三”,”测试数据四” ,”测试数据一”,”测试数据二”,”测试数据三”,”测试数据四”) private val mAdapter by lazy { ListDialogAdapter() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)rv_dialog_bottom_list.layoutManager = LinearLayoutManager(context)rv_dialog_bottom_list.setHasFixedSize(true)rv_dialog_bottom_list.adapter = mAdaptermAdapter.setList(list)
}
}
简单布局:```kotlin<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="match_parent"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_dialog_bottom_list"android:layout_width="match_parent"android:layout_height="200dp"/></RelativeLayout>
简单的 Item 布局:
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="50dp"><TextViewandroid:id="@+id/tv_item_list_dialog_title"android:layout_width="match_parent"android:layout_height="match_parent"android:text="任意文字标签"android:gravity="center"/></RelativeLayout>
3.4 占据全屏对话框
对话框占据全屏,初始暂时大约占据大半个屏幕,上滑占据全屏,效果如下:
对话框:
class FullListDialog(context: Context): BottomSheetDialog(context) {init {setContentView(R.layout.dialog_bottom_list)setCancelable(true)setCanceledOnTouchOutside(true)}val list = arrayListOf<String>("测试数据一","测试数据二","测试数据三","测试数据四","测试数据一","测试数据二","测试数据三","测试数据四","测试数据二","测试数据三","测试数据四","测试数据一","测试数据二","测试数据三","测试数据四" ,"测试数据一","测试数据二","测试数据三","测试数据四")private val mAdapter by lazy { ListDialogAdapter() }override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)rv_dialog_bottom_list_list.layoutManager = LinearLayoutManager(context)rv_dialog_bottom_list_list.setHasFixedSize(true)rv_dialog_bottom_list_list.adapter = mAdaptermAdapter.setList(list)}}
对话框布局:
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="列表标题"android:textSize="20dp"android:layout_gravity="center"android:gravity="center"android:background="@color/white"android:padding="@dimen/m10"/><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_dialog_bottom_list_list"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>
adapter 和 Item 布局和上面3.3的一样。
demo 地址
- 当内容不够全屏时,设置全屏,并且设置下滑跳过折叠直接关闭。
对话框布局,设置最小高度超过屏幕高度,同时对话框里面设置如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_dialog_bottom_list"android:layout_width="match_parent"android:layout_height="match_parent"/><!-- android:minHeight="900dp"设置最小高度实现全屏--></LinearLayout>
init {setContentView(R.layout.dialog_bottom)setCancelable(true)//是否可以滑动关闭setCanceledOnTouchOutside(true)//是否可以点击外部关闭// //设置全屏// behavior.state = BottomSheetBehavior.STATE_EXPANDED// //设置下滑跳过折叠态// behavior.skipCollapsed = true}
四、参考
BottomSheet、BottomSheetDialog使用详解
底部弹出抽屉BottomSheetDialogFragment,圆角背景,去除层叠,百分比设置高度【总结】
BottomSheetDialogFragment使用的注意点
Material Design 控件知识梳理(3) - BottomSheet && BottomSheetDialog && BottomSheetDialogFragment
Android评论框,类似抖音评论弹框
