一、效果图,不太清晰

本想一次全部录下来做成 gif 图,可惜高清 gif 图太大了,无法上传,只能换成普清模式,一次录一段,有更好的录制 gif 图的方法可以留言告知。现在只能勉强看看。
iShot2020-08-0321.58.23.gif

二、实现类似抖音拖拽评论框效果

首先布局的最外层要是CoordinatorLayout ,然后对话框的最外层要加上这三个属性:

  1. app:behavior_hideable="true"
  2. app:behavior_peekHeight="50dp"
  3. app:layout_behavior="@string/bottom_sheet_behavior"
  • app:behavior_hideable=”true” —-> 可选设置,是否支持隐藏,设置为 false 或是不设置就是不支持,就不能调用隐藏的方法setState(BottomSheetBehavior.STATE_HIDDEN)
  • app:behavior_peekHeight=”50dp” —-> 必选设置,收起高度,上图中黄色区域
  • app:layout_behavior 必选设置,设置以后才会有对话框效果

完整的界面布局:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. xmlns:app="http://schemas.android.com/apk/res-auto">
  6. <androidx.core.widget.NestedScrollView
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent">
  9. <LinearLayout
  10. android:layout_width="match_parent"
  11. android:layout_height="wrap_content"
  12. android:orientation="vertical">
  13. <LinearLayout
  14. android:layout_width="match_parent"
  15. android:layout_height="wrap_content">
  16. <Button
  17. android:id="@+id/btn_mddialog_bottomdialog"
  18. android:layout_width="wrap_content"
  19. android:layout_height="wrap_content"
  20. android:text="bottomSheetDialog"
  21. android:textAllCaps="false"/>
  22. <Button
  23. android:id="@+id/btn_mddialog_bottomdialog2"
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:text="bottomSheetDialog"
  27. android:textAllCaps="false"/>
  28. </LinearLayout>
  29. <LinearLayout
  30. android:layout_width="match_parent"
  31. android:layout_height="wrap_content">
  32. <Button
  33. android:id="@+id/btn_mddialog_list"
  34. android:layout_width="wrap_content"
  35. android:layout_height="wrap_content"
  36. android:text="bottomSheetDialog-list"
  37. android:textAllCaps="false"/>
  38. </LinearLayout>
  39. <LinearLayout
  40. android:layout_width="match_parent"
  41. android:layout_height="wrap_content">
  42. <Button
  43. android:id="@+id/btn_mddialog_expande"
  44. android:layout_width="wrap_content"
  45. android:layout_height="wrap_content"
  46. android:text="底部对话框展开"
  47. android:textAllCaps="false"/>
  48. <Button
  49. android:id="@+id/btn_mddialog_hide"
  50. android:layout_width="wrap_content"
  51. android:layout_height="wrap_content"
  52. android:text="底部对话框隐藏"
  53. android:textAllCaps="false"
  54. android:layout_marginStart="5dp"
  55. android:layout_marginEnd="5dp"/>
  56. <Button
  57. android:id="@+id/btn_mddialog_collose"
  58. android:layout_width="wrap_content"
  59. android:layout_height="wrap_content"
  60. android:text="底部对话框关闭"
  61. android:textAllCaps="false"/>
  62. </LinearLayout>
  63. </LinearLayout>
  64. </androidx.core.widget.NestedScrollView>
  65. <!-- 底部可以拉出的对话框,仿抖音-->
  66. <LinearLayout
  67. android:id="@+id/ll_mddialog_bottom"
  68. android:layout_width="match_parent"
  69. android:layout_height="wrap_content"
  70. android:orientation="vertical"
  71. app:behavior_hideable="false"
  72. app:behavior_peekHeight="50dp"
  73. app:layout_behavior="@string/bottom_sheet_behavior"
  74. android:background="@color/white">
  75. <TextView
  76. android:id="@+id/tv_mddialog_bottomDialog"
  77. android:layout_width="match_parent"
  78. android:layout_height="50dp"
  79. android:text="拖拽可以拉出对话框"
  80. android:textColor="@color/white"
  81. android:gravity="center"
  82. android:background="@color/yellow_FF9B52"/>
  83. <androidx.recyclerview.widget.RecyclerView
  84. android:id="@+id/rv_mddialog_bottom"
  85. android:layout_width="match_parent"
  86. android:layout_height="200dp"/>
  87. </LinearLayout>
  88. </androidx.coordinatorlayout.widget.CoordinatorLayout>

activity 部分:

  1. class MdDialogActivity: AppCompatActivity() {
  2. override fun onCreate(savedInstanceState: Bundle?) {
  3. super.onCreate(savedInstanceState)
  4. setContentView(R.layout.activity_mddialog)
  5. //bottomdialog test
  6. btn_mddialog_bottomdialog.setOnClickListener {
  7. showBottomDialog()
  8. }
  9. btn_mddialog_bottomdialog2.setOnClickListener {
  10. val dialog = SimpleDialog(this)
  11. dialog.show()
  12. }
  13. btn_mddialog_list.setOnClickListener {
  14. val dialog = ListDialog(this)
  15. dialog.show()
  16. }
  17. //把这个底部菜单和一个BottomSheetBehavior关联起来
  18. val behavior = BottomSheetBehavior.from(ll_mddialog_bottom)
  19. //底部对话框展开点击
  20. btn_mddialog_expande.setOnClickListener {
  21. if(behavior.state == BottomSheetBehavior.STATE_EXPANDED) {//展开不管
  22. return@setOnClickListener
  23. }else{
  24. behavior.setState(BottomSheetBehavior.STATE_EXPANDED)
  25. }
  26. }
  27. //底部对话框隐藏点击
  28. btn_mddialog_hide.setOnClickListener {
  29. behavior.setState(BottomSheetBehavior.STATE_HIDDEN)
  30. }
  31. //底部对话框关闭
  32. btn_mddialog_collose.setOnClickListener {
  33. behavior.setState(BottomSheetBehavior.STATE_COLLAPSED)
  34. }
  35. //初始化底部对话框列表
  36. initBottomList()
  37. // tv_mddialog_bottomDialog.setOnClickListener {
  38. // if(behavior.state == BottomSheetBehavior.STATE_EXPANDED) {//展开就隐藏
  39. // behavior.setState(BottomSheetBehavior.STATE_HIDDEN)
  40. // }else {//隐藏就展开
  41. // behavior.setState(BottomSheetBehavior.STATE_EXPANDED)
  42. // }
  43. // }
  44. }
  45. val list = arrayListOf<String>("测试数据一","测试数据二","测试数据三","测试数据四"
  46. ,"测试数据一","测试数据二","测试数据三","测试数据四")
  47. val mAdapter by lazy { ListDialogAdapter() }
  48. private fun initBottomList() {
  49. rv_mddialog_bottom?.run {
  50. layoutManager = LinearLayoutManager(context)
  51. adapter = mAdapter
  52. }
  53. mAdapter.setList(list)
  54. }
  55. private fun showBottomDialog() {//可以滑动,向下滑动关闭
  56. val dialog = BottomSheetDialog(this)
  57. dialog.setCanceledOnTouchOutside(true)//设置点击空白处是否消失
  58. dialog.setCancelable(false)//设置是否可以滑动关闭
  59. val view = layoutInflater.inflate(R.layout.dialog_bottom_simple, null, false)
  60. dialog.setContentView(view)
  61. view.findViewById<TextView>(R.id.tv_dialog_bottom_simple_title)
  62. .text = "第一条标签"
  63. dialog.show()
  64. }
  65. }

三、BottomSheetDialog 简单使用

3.1 简单对话框实现

  1. setCancelable(false)//是否可以滑动关闭
  2. setCanceledOnTouchOutside(true)//是否可以点击外部关闭

效果图:
image.png
对话框实现类:

  1. private fun showBottomDialog() {//可以滑动,向下滑动关闭
  2. val dialog = BottomSheetDialog(this)
  3. dialog.setCanceledOnTouchOutside(true)//设置点击空白处是否消失
  4. val view = layoutInflater.inflate(R.layout.dialog_bottom_simple, null, false)
  5. dialog.setContentView(view)
  6. view.findViewById<TextView>(R.id.tv_dialog_bottom_simple_title)
  7. .text = "第一条标签"
  8. dialog.show()
  9. }

简单对话框布局:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <LinearLayout
  6. android:layout_width="match_parent"
  7. android:layout_height="wrap_content"
  8. android:orientation="vertical"
  9. android:background="@color/white">
  10. <TextView
  11. android:id="@+id/tv_dialog_bottom_simple_title"
  12. android:layout_width="match_parent"
  13. android:layout_height="@dimen/dp_40"
  14. android:text="设置备注及星标"
  15. android:gravity="center_vertical"
  16. android:paddingStart="@dimen/m10"/>
  17. <TextView
  18. android:layout_width="match_parent"
  19. android:layout_height="@dimen/dp_40"
  20. android:text="设置备注及星标"
  21. android:gravity="center_vertical"
  22. android:paddingStart="@dimen/m10"
  23. />
  24. <TextView
  25. android:layout_width="match_parent"
  26. android:layout_height="@dimen/dp_40"
  27. android:text="设置备注及星标"
  28. android:gravity="center_vertical"
  29. android:paddingStart="@dimen/m10"
  30. />
  31. <TextView
  32. android:layout_width="match_parent"
  33. android:layout_height="@dimen/dp_40"
  34. android:text="设置备注及星标"
  35. android:gravity="center_vertical"
  36. android:paddingStart="@dimen/m10"
  37. />
  38. </LinearLayout>
  39. </RelativeLayout>

3.2 简单对话框实现圆角背景

  • 1.效果图

image.png

    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 = “第一个标签” }

}

  1. - 3. 对话框布局
  2. ```kotlin
  3. <?xml version="1.0" encoding="utf-8"?>
  4. <RelativeLayout
  5. xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. >
  8. <LinearLayout
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:orientation="vertical"
  12. android:background="@drawable/bg_white_fillet_10">
  13. <TextView
  14. android:id="@+id/tv_dialog_bottom_simple_title"
  15. android:layout_width="match_parent"
  16. android:layout_height="@dimen/dp_40"
  17. android:text="设置备注及星标"
  18. android:gravity="center_vertical"
  19. android:paddingStart="@dimen/m10"/>
  20. <TextView
  21. android:layout_width="match_parent"
  22. android:layout_height="@dimen/dp_40"
  23. android:text="设置备注及星标"
  24. android:gravity="center_vertical"
  25. android:paddingStart="@dimen/m10"
  26. />
  27. <TextView
  28. android:layout_width="match_parent"
  29. android:layout_height="@dimen/dp_40"
  30. android:text="设置备注及星标"
  31. android:gravity="center_vertical"
  32. android:paddingStart="@dimen/m10"
  33. />
  34. <TextView
  35. android:layout_width="match_parent"
  36. android:layout_height="@dimen/dp_40"
  37. android:text="设置备注及星标"
  38. android:gravity="center_vertical"
  39. android:paddingStart="@dimen/m10"
  40. />
  41. </LinearLayout>
  42. </RelativeLayout>
    1. 圆角背景

      1. <?xml version="1.0" encoding="utf-8"?>
      2. <shape xmlns:android="http://schemas.android.com/apk/res/android">
      3. <solid android:color="@color/white"/>
      4. <corners android:topLeftRadius="@dimen/m10"
      5. android:topRightRadius="@dimen/m10"/>
      6. </shape>
  • 5.代码实现背景透明

    1. btn_mddialog_bottomdialog2.setOnClickListener {
    2. val dialog = SimpleDialog(this)
    3. //dialog.window!!.setDimAmount(0f)//;设置窗体背景透明
    4. //设置背景透明,以便显示圆角背景
    5. dialog.window!!.findViewById<View>(R.id.design_bottom_sheet)
    6. .setBackgroundColor(Color.TRANSPARENT)
    7. dialog.show()
    8. }

    3.3 固定高度的 RecycelerView 对话框

    对 RecyclerView 设置固定高度可以参考这个RecyclerView 设置固定数目 Item,这里简单做个示例,固定了高度,效果图如下:
    iShot2020-08-0920.11.55.gif
    对话框代码: ```kotlin class ListDialog(context: Context): BottomSheetDialog(context) { init {

    1. setContentView(R.layout.dialog_bottom)
    2. setCancelable(false)//是否可以滑动关闭
    3. setCanceledOnTouchOutside(true)//是否可以点击外部关闭

    } val list = arrayListOf(“测试数据一”,”测试数据二”,”测试数据三”,”测试数据四” ,”测试数据一”,”测试数据二”,”测试数据三”,”测试数据四”) private val mAdapter by lazy { ListDialogAdapter() } override fun onCreate(savedInstanceState: Bundle?) {

    1. super.onCreate(savedInstanceState)
    2. rv_dialog_bottom_list.layoutManager = LinearLayoutManager(context)
    3. rv_dialog_bottom_list.setHasFixedSize(true)
    4. rv_dialog_bottom_list.adapter = mAdapter
    5. mAdapter.setList(list)
  1. }

}

  1. 简单布局:
  2. ```kotlin
  3. <RelativeLayout
  4. xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
  5. android:layout_height="match_parent">
  6. <androidx.recyclerview.widget.RecyclerView
  7. android:id="@+id/rv_dialog_bottom_list"
  8. android:layout_width="match_parent"
  9. android:layout_height="200dp"/>
  10. </RelativeLayout>

简单的 Item 布局:

  1. <RelativeLayout
  2. xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
  3. android:layout_height="50dp">
  4. <TextView
  5. android:id="@+id/tv_item_list_dialog_title"
  6. android:layout_width="match_parent"
  7. android:layout_height="match_parent"
  8. android:text="任意文字标签"
  9. android:gravity="center"
  10. />
  11. </RelativeLayout>

adapter 很简单,就设置一个中间的文字就可以了。

3.4 占据全屏对话框

对话框占据全屏,初始暂时大约占据大半个屏幕,上滑占据全屏,效果如下:
iShot2020-08-0920.12.22.gif
对话框:

  1. class FullListDialog(context: Context): BottomSheetDialog(context) {
  2. init {
  3. setContentView(R.layout.dialog_bottom_list)
  4. setCancelable(true)
  5. setCanceledOnTouchOutside(true)
  6. }
  7. val list = arrayListOf<String>("测试数据一","测试数据二","测试数据三","测试数据四"
  8. ,"测试数据一","测试数据二","测试数据三","测试数据四","测试数据二","测试数据三","测试数据四"
  9. ,"测试数据一","测试数据二","测试数据三","测试数据四" ,"测试数据一","测试数据二","测试数据三","测试数据四"
  10. )
  11. private val mAdapter by lazy { ListDialogAdapter() }
  12. override fun onCreate(savedInstanceState: Bundle?) {
  13. super.onCreate(savedInstanceState)
  14. rv_dialog_bottom_list_list.layoutManager = LinearLayoutManager(context)
  15. rv_dialog_bottom_list_list.setHasFixedSize(true)
  16. rv_dialog_bottom_list_list.adapter = mAdapter
  17. mAdapter.setList(list)
  18. }
  19. }

对话框布局:

  1. <LinearLayout
  2. xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. android:orientation="vertical">
  5. <TextView
  6. android:layout_width="match_parent"
  7. android:layout_height="wrap_content"
  8. android:text="列表标题"
  9. android:textSize="20dp"
  10. android:layout_gravity="center"
  11. android:gravity="center"
  12. android:background="@color/white"
  13. android:padding="@dimen/m10"
  14. />
  15. <androidx.recyclerview.widget.RecyclerView
  16. android:id="@+id/rv_dialog_bottom_list_list"
  17. android:layout_width="match_parent"
  18. android:layout_height="match_parent"/>
  19. </LinearLayout>

adapter 和 Item 布局和上面3.3的一样。
demo 地址

  • 当内容不够全屏时,设置全屏,并且设置下滑跳过折叠直接关闭。

对话框布局,设置最小高度超过屏幕高度,同时对话框里面设置如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6. <androidx.recyclerview.widget.RecyclerView
  7. android:id="@+id/rv_dialog_bottom_list"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent"
  10. />
  11. <!-- android:minHeight="900dp"设置最小高度实现全屏-->
  12. </LinearLayout>
  1. init {
  2. setContentView(R.layout.dialog_bottom)
  3. setCancelable(true)//是否可以滑动关闭
  4. setCanceledOnTouchOutside(true)//是否可以点击外部关闭
  5. // //设置全屏
  6. // behavior.state = BottomSheetBehavior.STATE_EXPANDED
  7. // //设置下滑跳过折叠态
  8. // behavior.skipCollapsed = true
  9. }

四、参考

BottomSheet、BottomSheetDialog使用详解
底部弹出抽屉BottomSheetDialogFragment,圆角背景,去除层叠,百分比设置高度【总结】
BottomSheetDialogFragment使用的注意点
Material Design 控件知识梳理(3) - BottomSheet && BottomSheetDialog && BottomSheetDialogFragment
Android评论框,类似抖音评论弹框