BottomSheetDialog踩坑记录(背景透明,圆角,折叠,输入框和软键盘)

BottomSheetDialog是原生实现的BottomSheet的dialog模式,适合很多场景下的底部弹窗功能,在此次记录下踩坑内容。

1. 关于布局的实现

BottomSheetDialog内部的布局实现及其简单,就是一个对CoordinatorLayout
的运用,XML原文如下:

<FrameLayout
    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/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinator"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <View
            android:id="@+id/touch_outside"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:importantForAccessibility="no"
            android:soundEffectsEnabled="false"
            tools:ignore="UnusedAttribute"/>

        <FrameLayout
            android:id="@+id/design_bottom_sheet"
            style="?attr/bottomSheetStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|top"
            app:layout_behavior="@string/bottom_sheet_behavior"/>

    </android.support.design.widget.CoordinatorLayout>

</FrameLayout>

其中id为design_bottom_sheet就是我们在调用setContentView()方法时往里塞的view的父布局,因此这个布局也就和实现圆角有关系了。

2.关于背景透明

网上其实有好多方法介绍如何让背景透明起来的
方法基本都是以下两种:

         mDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
         
         mDialog.getWindow().findViewById(R.id.design_bottom_sheet)
        .setBackgroundResource(android.R.color.transparent);

实际上可能在某些版本上可用,但是在笔者实际测试以后,发现这两个操作都没有实际上生效

在这里插入图片描述
明显可以看出是有个灰色的阴影效果无法去除,
最终,解决方案是:

        if (mDialog.getWindow() != null) {
            WindowManager.LayoutParams params = mDialog.getWindow().getAttributes();
            params.dimAmount = 0.0f;
            mDialog.getWindow().setAttributes(params);
        }

这样设置下自己的dialog之后,就可以去掉那层灰色的样式了
在这里插入图片描述
这种情况下,就实现了没有阴影效果的底部弹出框了。

3. 关于底部弹窗的圆角

很多时候我们不止要实现底部弹窗,还要实现底部弹窗的圆角,那么该怎么处理呢?
其实只要在setContentView()放入的view的父布局加上需要的圆角shape就OK了
在这里插入图片描述
这个shape的圆角还有不懂怎么加的同学们请自觉百度吧
有的时候我们会改变一下底部弹窗的颜色,那么就会出现这个问题了
在这里插入图片描述
弹窗的圆角下班还有一点点白色,有经验的同学一看就明白了,那是因为咱们的view底部还有一个白色的父布局,这个父布局其实就是之前说的id是design_bottom_sheet的FrameLayout了,那么简单的处理一下就OK了

 FrameLayout bottom = mDialog.findViewById(R.id.design_bottom_sheet);
        if (bottom != null) {
            bottom.setBackgroundResource(android.R.color.transparent);
        }

这样把白色的父布局就会被处理掉了,咱们的圆角就比较合理的展示出来了。
然后,由于北京是透明的了,那么其实合理的运用一下padding和margin,就可以实现悬浮层的效果,这里就不赘述了。

4. 关于折叠

这个dialog又一个很有趣的现象,就是可以折叠,因为内部毕竟是一个
CoordinatorLayout实现的嘛,其实折叠主要是靠BottomSheetBehavior来进行的操作

BottomSheetBehavior<View> behavior = BottomSheetBehavior.
                from((View) mDialogContentView.getParent());

可以通过这个方法来控制默认不折叠:

behavior.setSkipCollapsed(true);

这个方法用来控制可以全部收起,就是折叠之后在往下拉就会整个底部收起来:

behavior.setHideable(true);

这个方法来控制最小折叠高度:

  behavior.setPeekHeight(xxx);

那么就有些同学发现,其实我默认展开之后,下拉会折叠到一个高度,然后需要再次下拉才能完全隐藏,那么怎么来取消这个方式呢,简单的来说就是通过上边的代码来实现的了,只要将这个方法的参数传入屏幕高度,那么就不会再有下拉会折叠一下的效果了

 Display defaultDisplay = activity.getWindowManager().getDefaultDisplay();
        Point point = new Point();
        defaultDisplay.getSize(point);
        behavior.setPeekHeight(point.y);

这样会隐藏底部弹出的那部分界面,但是没有真正的dismiss 当前的dialog
所以还需要加入以下监听,来隐藏dialog:

behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                //当完全隐藏时,直接消除dialog
                if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                    mDialog.dismiss();
                }
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {

            }
        });

5.带EditText的情况下,有关软键盘的问题:

很多时候我们隐藏软键盘会调用:

  InputMethodManager imm = null;
        imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (getWindow() != null) {
            view = getWindow().getCurrentFocus();
        }
        if (null != view && imm != null) {
            imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }

这种方法,但是在BottomSheetDialog的EditText使用时,会出现一个很有意思的问题,那就是view = getWindow().getCurrentFocus();这个返回的是null
那么实际隐藏软件盘的操作就是失败的了
如何避免这个问题呢,目前我使用的是自定义的BottomSheetDialog,通过这个dialog来处理隐藏

public class KeyBoardBottomSheetDialog extends BottomSheetDialog {

    public KeyBoardBottomSheetDialog(@NonNull Context context) {
        super(context);
    }

    public KeyBoardBottomSheetDialog(@NonNull Context context, int theme) {
        super(context, theme);
    }

    protected KeyBoardBottomSheetDialog(@NonNull Context context, boolean cancelable, OnCancelListener cancelListener) {
        super(context, cancelable, cancelListener);
    }

    @Override
    public void dismiss() {
        //因为dismiss之后当前焦点的EditText无法获取,所以自定义一下
        hideKeyBoard();
        super.dismiss();
    }

    public void hideKeyBoard() {
        View view = null;
        InputMethodManager imm = null;
        imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (getWindow() != null) {
            view = getWindow().getCurrentFocus();
        }
        if (null != view && imm != null) {
            imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

}

这样,只要调用自定义dialog的hideKeyBoard()方法,就可以实现
,就可以实现隐藏软键盘了。

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值