Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >BottomSheetDialog 使用详解,设置圆角、固定高度、默认全屏等

BottomSheetDialog 使用详解,设置圆角、固定高度、默认全屏等

作者头像
yechaoa
发布于 2022-06-10 06:46:14
发布于 2022-06-10 06:46:14
4.4K00
代码可运行
举报
文章被收录于专栏:移动开发专栏移动开发专栏
运行总次数:0
代码可运行

1.效果

MD风格的底部弹窗,比自定义dialogpopupwindow使用更简单,功能也更强大。

其实细分来说,是BottomSheetBottomSheetDialogBottomSheetDialogFragment

2.BottomSheet

与主界面同层级关系,可以事件触发,如果有设置显示高度的话,也可以拉出来,且不会影响主界面的交互。

XML

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.yechaoa.materialdesign.activity.BottomSheetActivity">

    <include
        android:id="@+id/include"
        layout="@layout/layout_toolbar" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:gravity="center"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn_bottom_sheet"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="32dp"
            android:text="BottomSheet"
            android:textAllCaps="false" />

        ...

    </LinearLayout>


    <LinearLayout
        android:id="@+id/ll_bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:behavior_peekHeight="80dp"
        app:layout_behavior="@string/bottom_sheet_behavior"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@android:color/holo_red_light"
            android:gravity="center"
            android:text="上拉解锁隐藏功能"
            android:textColor="@color/white"
            android:textSize="20sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@android:color/holo_blue_light"
            android:gravity="center"
            android:text="a"
            android:textSize="20sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@android:color/holo_orange_dark"
            android:gravity="center"
            android:text="b"
            android:textSize="20sp" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="@android:color/holo_green_light"
            android:gravity="center"
            android:text="c"
            android:textSize="20sp" />

    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
  • 注意,这里需要协调布局CoordinatorLayout包裹才行
  • app:behavior_peekHeight显示高度,不显示的话设置为0即可
  • app:layout_behavior 标示这是一个bottom_sheet

以上3个条件都是必须的。

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        btn_bottom_sheet.setOnClickListener {
            val behavior = BottomSheetBehavior.from(ll_bottom_sheet)
            if (behavior.state == BottomSheetBehavior.STATE_EXPANDED) {
                //如果是展开状态,则关闭,反之亦然
                behavior.state = BottomSheetBehavior.STATE_COLLAPSED
            } else {
                behavior.state = BottomSheetBehavior.STATE_EXPANDED
            }
        }
  • STATE_COLLAPSED: 折叠状态
  • STATE_EXPANDED: 展开状态
  • STATE_DRAGGING : 过渡状态
  • STATE_SETTLING: 视图从脱离手指自由滑动到最终停下的这一小段时间
  • STATE_HIDDEN : 默认无此状态(可通过app:behavior_hideable 启用此状态),启用后用户将能通过向下滑动完全隐藏 bottom sheet

3.BottomSheetDialog

可以看到弹出来之后是有一个半透明的蒙层的,这时候是影响主界面交互的,也就意味着此时BottomSheetDialog的优先级是要高于主界面的。

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
            val bottomSheetDialog = BottomSheetDialog(this)
            bottomSheetDialog.setContentView(R.layout.dialog_bottom_sheet)
            bottomSheetDialog.show()

dialog_bottom_sheet:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:paddingTop="80dp"
    android:paddingBottom="80dp"
    android:text="BottomSheetDialog"
    android:textSize="30sp"
    android:textStyle="bold" />

比较简单的使用方式,直接实例化之后setContentView,然后调用show就可以了。

这里只是一个展示效果,实际上使用场景可能会复杂一些,还要做一些操作等等,所以,也可以自定义dialog继承自BottomSheetDialog,然后处理自己的业务逻辑。

比如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyDialog(context: Context) : BottomSheetDialog(context) {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }
  
}

4.BottomSheetDialogFragment

效果跟BottomSheetDialog差不多,代码跟DialogFragment差不多。

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class MyBottomSheetDialog : BottomSheetDialogFragment() {

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = super.onCreateDialog(savedInstanceState)
        val view = LayoutInflater.from(context).inflate(R.layout.dialog_my_bottom_sheet, null)
        dialog.setContentView(view)
        initView(view)
        return dialog
    }

    private fun initView(rootView: View) {
        //do something
        rootView.tv_cancel.setOnClickListener { dismiss() }

    }
}

在创建dialog的时候引入布局,然后setContentView即可。

调用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MyBottomSheetDialog().show(supportFragmentManager, "MyBottomSheetDialog")
  • FragmentManager
  • tag

但是在实际开发中,我们的需求可能并不能满足于此,比如上部分圆角效果指定高度

5.圆角效果

  • 先设置原有背景透明

style.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--实现BottomSheetDialog圆角效果-->
    <style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
    </style>
    <style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
        <item name="android:background">@android:color/transparent</item>
    </style>
  • onCreate中设置style
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setStyle(STYLE_NORMAL, R.style.BottomSheetDialog)
    }
  • 设置我们自己的style

根布局的view上设置background

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
android:background="@drawable/shape_sheet_dialog_bg"

shape_sheet_dialog_bg

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners
        android:topLeftRadius="15dp"
        android:topRightRadius="15dp" />
    <solid android:color="@color/white" />
</shape>

6.去掉背景阴影

可以看到是没有阴影蒙版的,还是style,设置backgroundDimEnabledfalse即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--实现BottomSheetDialog圆角效果 且无背景阴影-->
    <style name="BottomSheetDialogBg" parent="Theme.Design.Light.BottomSheetDialog">
        <item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
        <item name="android:backgroundDimEnabled">false</item>
    </style>
    <style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
        <item name="android:background">@android:color/transparent</item>
    </style>

7.设置固定高度

可以看到这个弹窗一开始并不是完全展开的,但是可以继续拉出来。

代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    override fun onStart() {
        super.onStart()
        //拿到系统的 bottom_sheet
        val view: FrameLayout = dialog?.findViewById(R.id.design_bottom_sheet)!!
        //获取behavior
        val behavior = BottomSheetBehavior.from(view)
        //设置弹出高度
        behavior.peekHeight = 350
    }

有一个peekHeight属性可以设置高度,但是这个api并没有开放给我们,不过也有解决办法

我们可以查看bottomSheetDialog.setContentView的源码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  @Override
  public void setContentView(@LayoutRes int layoutResId) {
    super.setContentView(wrapInBottomSheet(layoutResId, null, null));
  }

这里调用了wrapInBottomSheet,继续探索

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  private View wrapInBottomSheet(int layoutResId, @Nullable View view, @Nullable ViewGroup.LayoutParams params) {
    ensureContainerAndBehavior(); 
    ...
    return container;
  }

多余的可以不用看,直接探索ensureContainerAndBehavior();方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  /** Creates the container layout which must exist to find the behavior */
  private FrameLayout ensureContainerAndBehavior() {
    if (container == null) {
      container =
          (FrameLayout) View.inflate(getContext(), R.layout.design_bottom_sheet_dialog, null);

      FrameLayout bottomSheet = (FrameLayout) container.findViewById(R.id.design_bottom_sheet);
      behavior = BottomSheetBehavior.from(bottomSheet);
      behavior.addBottomSheetCallback(bottomSheetCallback);
      behavior.setHideable(cancelable);
    }
    return container;
  }

到这里,我们就可以看到源码是怎么获取behavior的了,获取到behavior之后就可以调用peekHeight设置高度了。

8.设置默认全屏显示

既然有了上面的方法,是不是有思路了,那有人说了,我把高度设置全屏不就完事了吗

事实上还真不行,BottomSheetDialogFragment只会显示实际高度,即布局有效高度,即使根布局高度match_parent也不行。

既然我们自己的view不行,那就从BottomSheetDialogFragment本身下手,还记得上面我们通过dialog?.findViewById(R.id.design_bottom_sheet)!!拿到的view吗,我们试一下设置这个view的高度行不行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
view.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT

看看效果

首先是像默认效果一样,当内容大于等于全屏的时候,会先到达一个高度,即上面效果的高度,然后继续向上滑的话,可以铺满全屏。

虽然不是预想的效果,但是既然还可以向上滑动至全屏,说明我们设置的高度是有效的,只是没有一次性展开而已,还记得前面提到的状态state吗,设置一下试试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
behavior.state = BottomSheetBehavior.STATE_EXPANDED

看看效果

可以了,这下是直接就全屏了,但是向下拉的时候发现,并没有一次性收起,而是先停在了全屏时显示的默认位置,我们再设置高度为全屏试试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
behavior.peekHeight = 3000

实际高度可以自己计算

最终代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    override fun onStart() {
        super.onStart()
        //拿到系统的 bottom_sheet
        val view: FrameLayout = dialog?.findViewById(R.id.design_bottom_sheet)!!
        //设置view高度
        view.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
        //获取behavior
        val behavior = BottomSheetBehavior.from(view)
        //设置弹出高度
        behavior.peekHeight = 3000
        //设置展开状态
        behavior.state = BottomSheetBehavior.STATE_EXPANDED
    }

看看最终效果

效果是ok的,但是也有一点点不足,我们下拉的距离快到底部的时候才能关闭,所以建议在弹窗中也加上关闭的操作。

9.监听展开收起

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
            
            override fun onStateChanged(bottomSheet: View, newState: Int) {
                when(newState){
                    BottomSheetBehavior.STATE_EXPANDED->{}
                    BottomSheetBehavior.STATE_COLLAPSED->{}
                    BottomSheetBehavior.STATE_DRAGGING->{}
                    BottomSheetBehavior.STATE_SETTLING->{}
                    BottomSheetBehavior.STATE_HIDDEN->{}
                }
            }

            override fun onSlide(bottomSheet: View, slideOffset: Float) {

            }

        })

可以写在dialog里,也可以接口抛出去。

10.Github

https://github.com/yechaoa/MaterialDesign

ok,至此BottomSheetDialog相关的功能完全演示完了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-11-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
给BottomSheetDialog 设置默认高度,全屏显示
通过源码发现,拿到BottomSheetBehavior就可以很方便设置peekHight,设置state
用户5584592
2021/05/28
6.1K0
Android材料设计之FloatingActionButton+Snackbar+SheetX3
本文把几个小东西讲一下 FloatingActionButton:浮动按钮 Snackbar:底弹框 BottomSheet:底抽屉 BottomSheetDialog :抽屉对话框 Bot
张风捷特烈
2018/12/19
9760
Android开发笔记(一百三十四)协调布局CoordinatorLayout
Android自5.0之后对UI做了较大的提升,一个重大的改进是推出了MaterialDesign库,而该库的基础即为协调布局CoordinatorLayout,几乎所有的design控件都依赖于该布局。协调布局的含义,指的是内部控件互相之前的动作关联,比如在A视图的位置发生变化之时,B视图的位置也按照某种规则来变化,仿佛弹钢琴有了协奏曲一般。 使用CoordinatorLayout时,要注意以下几点: 1、导入design库; 2、根布局采用android.support.design.widget.CoordinatorLayout; 3、CoordinatorLayout节点要添加命名空间声明xmlns:app="http://schemas.android.com/apk/res-auto"; CoordinatorLayout继承自ViewGroup,实现效果类似于RelativeLayout,若要指定子视图在整个页面中的位置,有以下几个办法: 1、使用layout_gravity属性,指定子视图在CoordinatorLayout内部的对齐方式。 2、使用app:layout_anchor和app:layout_anchorGravity属性,指定子视图相对于其它子视图的位置。其中app:layout_anchor表示当前以哪个视图做为参照物,app:layout_anchorGravity表示本视图相对于参照物的对齐方式。 3、使用app:layout_behavior属性,指定子视图相对于其它视图的行为,当对方的位置发生变化时,本视图的位置也要随之相应变化。 下面是使用anchor方式定义子视图方位的截图,其中红色方块位于整个页面的右上方:
aqi00
2019/01/18
2.3K0
BottomSheet底部动作条使用
底部动作条 底部动作条(Bottom Sheets)是一个从屏幕底部边缘向上滑出的一个面板,使用这种方式向用户呈现一组功能。底部动作条呈现了简单、清晰、无需额外解释的一组操作。 使用环境 底部动作条(Bottom Sheets)特别适合有三个或者三个以上的操作需要提供给用户选择、并且不需要对操作有额外解释的情景。如果只有两个或者更少的操作,或者需要详加描述的,可以考虑使用菜单(Menu)或者对话框替代。 底部动作条(Bottom Sheets)可以是列表样式的也可以是宫格样式的。宫格布局可以增加视觉的清晰
xiangzhihong
2018/02/05
1.9K0
BottomSheet底部动作条使用
听说谷歌Baba更新了 Material UI ...
Material Design,是谷歌在14年的IO大会上提出的一种新的理念,也被称为新的设计语言(也被称为“原材料设计”),称它为设计语言不为过,但是实际上,这仅仅是谷歌提倡的一种新的设计风格、理念以及设计基本原则。
贺biubiu
2019/06/10
3.1K0
用 CoordinatorLayout 处理滚动
原文地址:Handling Scrolls with CoordinatorLayout 原文作者:CODEPATH 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:Feximin 总览 CoordinatorLayout 扩展了完成 Google's Material Design 中的多种滚动效果的能力。目前,此框架提供了几种不需要写任何自定义动画代码就可以(使动画)工作的方式。这些效果包括: 上下滑动 Floating Action Button 以给 Sn
Android 开发者
2018/05/31
5K0
Android常用对话框大全——Dialog「建议收藏」
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/137960.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/23
4.4K0
Android常用对话框大全——Dialog「建议收藏」
Material Design之CollapsingToolbarLayout 相关属性和方法介绍
Material Design之CollapsingToolbarLayout 相关属性和方法介绍
103style
2022/12/19
1K0
Material Design之CollapsingToolbarLayout 相关属性和方法介绍
细说 AppbarLayout,如何理解可折叠 Toolbar 的定制
Material Design 是个好东西,它的出现使得 Android 也能定制高颜值的界面,并且指导了如果实现复杂炫丽的交互效果,而 Android Surpport Desgin 这个支持包就是 Android 官方对 Material Design 的代码实现。
Frank909
2019/01/14
3.3K1
【Android】这效果,我没法描述
前言 最近接到一个需求,这需求让我表示很尴尬。(下面是一些废话) 要求的效果是这样的,顶部有部分悬浮,接着是一些布局,在下面是几个可切换的Tab页面,然后滚动的时候~~吧啦吧啦吧啦吧啦~~ 还是
Gavin-ZYX
2018/05/18
1K0
CoordinatorLayout与滚动的处理
本博文专门讲解和CoordinatorLayout相关的知识点,这也是Design Support Library中最重要与最难的部分。
小小工匠
2021/08/16
8820
Android材料设计之Behavior攻坚战
接触目标view时才会回调:onStartNestedScroll 加了layout_behavior的View是child
张风捷特烈
2018/12/21
1.3K0
聊聊Android嵌套滑动
最近工作中遇到了需求是使用 Bottom-Sheet 交互的弹窗,使用了 design 包里面的 CoordinatorLayout 和 BottomSheetBehavior ,因为弹窗承载的页面相对来说还是比较复杂的页面,所以也踩了好几个坑。之前UI交互类的东西接触的也比较少,于是把Android里面嵌套滑动相关的内容也过了一遍,在这里做一些分享。 在嵌套滑动控件的场景中,可以在Android的事件分发机制本身做一些处理,外部拦截或者内部消化触摸事件。但是这样的解决方法有几个弊端:
烧麦程
2022/05/10
1.4K0
聊聊Android嵌套滑动
Material Design 实战 之第四弹 —— 卡片布局
首先这里准备用CardView来填充主题内容, CardView是用于实现卡片式布局效果的重要控件,由appcompat-v7库提供。 实际上,CardView也是一个FrameLayout,只是额外提供了圆角和阴影等效果,看上去会有立体的感觉。
凌川江雪
2018/10/09
2.3K0
Material Design 实战 之第四弹 —— 卡片布局
相关推荐
给BottomSheetDialog 设置默认高度,全屏显示
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验