Android Dialog 蒙版(背景)与导航栏颜色的问题

本文详细描述了一个开发者如何在Android中创建一个底部弹出的Dialog,通过调整主题和代码实现半透明背景,并使其与系统导航栏无缝融合的过程。作者分享了从问题排查到最终解决方案的一步步操作,包括使用`Theme.Holo.Dialog`主题、设置全屏、沉浸式状态栏和导航栏等技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本来是写一个底部弹出的dialog,背后一个半透明的背景。

很简单的一个需求。

1、写个布局

2、写个class继承Dialog。

public class ChooseWeChatDialog extends AppCompatDialog {
<style name="DefaultDialog" parent="Theme.AppCompat.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <!-- 是否开启半透明的背景 -->
        <item name="android:backgroundDimEnabled">true</item>
        <!-- 半透明的背景的透明度 -->
        <item name="android:backgroundDimAmount">0.6</item>
        <item name="android:windowFullscreen">false</item>
        <item name="android:windowActionBar">true</item>
    </style>

3、重写构造函数,传入theme

  public ChooseWeChatDialog(FragmentActivity context, OnClickBack onClickBack) {
        super(context, R.style.DefaultDialog);
        this.mContext = context;
        this.onClickBack = onClickBack;
    }

4、重写onCreate方法设置布局

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View contentView = LayoutInflater.from(mContext).inflate(R.layout.dialog_wechat_choose, null);
        ll_wechat = contentView.findViewById(R.id.ll_wechat);
        ll_wechat_friend = contentView.findViewById(R.id.ll_wechat_friend);
        setCanceledOnTouchOutside(true);
        setContentView(contentView);

然后show起来,然后发现出问题了,出来的结果是这样的

顶部的状态栏和底部的当行栏都带了系统自带的那个背景,顶部不用管,就是我想要的效果(现在是蓝色是因为底部的Activity还没有设置成沉浸式的)。但是底部就不行,看上就和格格不入。

就想着给底部改个颜色,白色就可以,想着TM挺简单的一个东西,改了两天没改好。

一个是自己太菜,不知道设置这东西的原理,只有到处去找别人实现的代码复制下来看效果,不满意又再换。结果你抄我我抄你的,试了两天都没有一个代码是生效的。

废话了, 最后这这么搞的:

1、dialog这样显示是因为没有全屏,底部导航栏的显示还在系统上,所以改不了。那么就先让dialog全屏,怎么让dialog全屏呢,通过theme就可以,把现在dialog的Theme的parent改成这个(为啥是这个,我也不知道为啥,但是这个效果是能满足我的)

 <style name="DefaultDialog" parent="@android:style/Theme.Holo.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:backgroundDimAmount">0.6</item>
        <item name="android:windowFullscreen">false</item>
        <item name="android:windowActionBar">true</item>
    </style>

2、这个时候你就发现是全屏了,但是底部导航栏直接变成黑色了,那就说明导航栏还是没给你,这个时候在代码中给dialog设置沉浸式的状态栏和导航栏(代码放在dialog 的 onCreat里面就可以,不用在show之后)

 // 保证dialog宽度占满
        Window window = getWindow();
        window.setGravity(Gravity.BOTTOM);
        window.getDecorView().setPadding(0, 0, 0, 0);
        WindowManager.LayoutParams layoutParams = window.getAttributes();
        layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        window.setAttributes(layoutParams);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0 全透明实现
            WindowManager.LayoutParams lp = getWindow().getAttributes();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
            }
            getWindow().setAttributes(lp);

            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
            window.setNavigationBarColor(Color.TRANSPARENT);

        } else {//4.4 全透明状态栏
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }

3、这个时候你就会发现dialog的展示放到了导航栏的下面,这是个好现象。你就可以在dialog的下面写一个白色背景的View,然后把这个view的高度设置为导航栏的高度

LinearLayout.LayoutParams vParams = (LinearLayout.LayoutParams) v_line.getLayoutParams();
vParams.height = ScreenUtils.getNavigationHeight(mContext);
v_line.setLayoutParams(vParams);

好了,这样看上去就正常了,虽然不是很优雅。但像我这种CV工程师,也就这个水平了。如果你有更好的办法,还请告诉我。

上个最后的效果图吧

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值