自定义 Dialog——宽度充满屏幕


在自定义底部选择省市区的 Dialog 时,可能会遇到这几个问题:

  1. 根据一般的 Dialog 布局的话,Dialog 会 show 在屏幕中间
  2. 跟布局使用宽高 match_parent,把主要布局放在最下面,上面空白部分用 View 填充,这样布局虽然放在最下面了,但是两边有去不掉的边距
  3. 设置 style 为全屏,可以去掉两边的边距,但是状态栏的颜色没有变化,强迫症受不了

完美的方案是利用 WindowManager 设置 Dialog 的布局和入场动画。

dialog

1.定义 style

定义自定义 Dialog 通用的 style

<!-- Dialog style-->
<style name="Theme.Light.NoTitle.Dialog" parent="@android:style/Theme.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowFrame">@null</item>
</style>

2.Dialog 进入离开动画(可选)

<!-- 底部 dialog 进入离开动画 -->
<style name="Animation.Bottom" parent="@android:style/Animation">
    <item name="android:windowEnterAnimation">@anim/bottom_up_in</item>
    <item name="android:windowExitAnimation">@anim/bottom_down_out</item>
</style>

/res/anim/bottom_up_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:interpolator/accelerate_decelerate">
    <translate
        android:duration="@android:integer/config_mediumAnimTime"
        android:fromYDelta="100%p"
        android:toYDelta="0"/>
    <alpha
        android:duration="@android:integer/config_mediumAnimTime"
        android:fromAlpha="0.95"
        android:toAlpha="1"/>
</set>

/res/anim/bottom_down_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="@android:integer/config_mediumAnimTime"
        android:fromYDelta="0"
        android:toYDelta="100%p" />
    <alpha
        android:duration="@android:integer/config_mediumAnimTime"
        android:fromAlpha="1"
        android:toAlpha="0.95" />
</set>

3.Dialog 构造器

public ChooseAddressDialog(Context context) {
    super(context, R.style.Theme_Light_NoTitle_Dialog);
    mContext = context;
    View view = LayoutInflater.from(context).inflate(R.layout.dialog, null);
    this.setContentView(view);
    // 设置 dialog 位于屏幕底部,并且设置出入动画
    setBottomLayout();
}

4.WindowManager 设置布局

/**
* 设置 dialog 位于屏幕底部,并且设置出入动画
*/
private void setBottomLayout() {
    Window win = getWindow();
    if (win != null) {
        win.getDecorView().setPadding(0, 0, 0, 0);
        WindowManager.LayoutParams lp = win.getAttributes();
        lp.width = WindowManager.LayoutParams.MATCH_PARENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        win.setAttributes(lp);
        // dialog 布局位于底部
        win.setGravity(Gravity.BOTTOM);
        // 设置进出场动画
        win.setWindowAnimations(R.style.Animation_Bottom);
    }
}

评论