Android进阶之路 - Dialog花样使用

因为项目中常用到Dialog,以前都是随手百度或者随手写一个,但是为了更好的偷懒,此篇主要为了方便日后的copy ~ 很适合初学的新手朋友 ~

弹框相关Blog

现在有很多好的三方框架,分分钟就可以用各种方式实现弹框效果,但是万变不离其中,都需要用到此篇中的通用知识,所以闲着没事儿可以稍微顺带瞧一眼 ~

基础了解

Dialog是Android自带的一款控件,一般用于需要弹框的场景,其实现方式主要分俩种 ~

  • 其一:自带的原始效果,包含常用的弹框、水平进度弹框、列表弹框、单选弹框、复选弹框,效果相对单一

  • 其二: 自定义Dialog,相比原始效果,可扩展的界面效果,动画效果更多一些

关于dialog属性的设置方式,一般有俩种

  • 创建Dialog时,手动在代码中设置Dialog属性
  • 创建dialog的style,在类内通过Dialog的构建方式传入已创建好的style,如下
   AlertDialog.Builder builder = new AlertDialog.Builder(context,R.style.BasicDialogStyle);

常用API

API含义
setTitle设置对话框的标题,比如“提示”、“警告”等
setMessage设置对话框要传达的具体信息
setIcon设置对话框的图标
setCancelable点击对话框以外的区域是否让对话框消失,默认为true
setPositiveButton设置正面按钮,表示“积极”、“确认”的意思,第一个参数为按钮上显示的文字,下同
setNegativeButton设置反面按钮,表示“消极”、“否认”、“取消”的意思
setNeutralButton设置中立按钮
setOnShowListener对话框显示时触发的事件
setOnCancelListener对话框消失时触发的事件

入门级

我这里借鉴了一位博友内部的列表对话框、单选对话框、复选对话框

主要记录一些Dialog的基础使用,加油哦 ~

普通对话框

这是一个入门的最初级弹框方法

Dialog创建后往往需要show()才会展示,同样要记得onDestroy()中返注册此Dialog,从而防止内存泄露 ~

在这里插入图片描述

示范Demo

   	/**
     * 初级对话框
     */
    public void simpleDialog(final Context mContext) {
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setIcon(R.mipmap.ic_launcher)
        		.setTitle("初级对话框")
                .setMessage("Dialog显示内容")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(mContext, "点击了确定按钮", Toast.LENGTH_SHORT).show();

                    }
                }).setNegativeButton("取消", null)
                .create()
                .show();
    }
水平进度条对话框

这是一个偶尔会用到的水平进度条弹框

提示:API

  /**
   * 设置方法 dialog.setProgressStyle(int style)
   * 水平进度条显示 ProgressDialog.STYLE_HORIZONTAL
   * 圆形进度条显示 ProgressDialog.STYLE_SPINNER
   * */
  progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
  //设置该属性后,点击外部可取消Dialog实现返回效果
  progressDialog.setCancelable(true);
  progressDialog.setCanceledOnTouchOutside(true);

在这里插入图片描述

示范Demo

    /**
     * 水平进度条对话框
     **/
    int count = 0;
    @SuppressWarnings("deprecation")
    public void levelProgressDialog(final Context mContext) {
        final ProgressDialog progressDialog = new ProgressDialog(mContext);
        progressDialog.setTitle("进度对话框");
        progressDialog.setIcon(R.mipmap.ic_launcher);
        progressDialog.setMessage("加载中...");
        // 水平进度条显示
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        // 圆形进度条显示
        // progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progressDialog.setCancelable(true);
        progressDialog.setButton("取消",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(mContext, "取消进度条对话框",
                                Toast.LENGTH_LONG).show();
                        progressDialog.cancel();
                        count = 0;
                    }
                });
        progressDialog.setMax(100);
        progressDialog.show();
        count = 0;
        new Thread() {
            @Override
            public void run() {
                while (count <= 100) {
                    progressDialog.setProgress(count++);
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        progressDialog.dismiss();
                        e.printStackTrace();
                    }
                }
                progressDialog.dismiss();
            }
        }.start();
    }
普通列表对话框

列表对话框的内容就是一列显示内容,需要用到构造器的setItems方法,参数一是列表数据,参数二是点击监听接口,我们要实现这样一个小功能,用户在点击某一项时弹出一个Toast提示选中项的内容 ~

/**
 * 列表对话框
 */
private void itemListDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
    builder.setTitle("选择你喜欢的课程:");
    builder.setCancelable(true);
    final String[] lesson = new String[]{"语文", "数学", "英语", "化学", "生物", "物理", "体育"};
    builder.setIcon(R.mipmap.ic_launcher);
    builder.setIcon(R.mipmap.tab_better_pressed)
            .setItems(lesson, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(getApplicationContext(), "你选择了" + lesson[which], Toast.LENGTH_SHORT).show();
                }
            }).create();
    //设置正面按钮
    builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    });
    //设置反面按钮
    builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    });
    AlertDialog dialog = builder.create();     //创建AlertDialog对象
    dialog.show();                              //显示对话框
}
单选对话框

单选对话框的内容就是一个单项选择列表,需要用到setSingleChoiceItems方法,参数一是列表数据,参数二是默认选中的item,参数三则是点击监听接口,我们要实现这样一个小功能,用户在选好某一项之后记下其选择,下次点开对话框时就默认选中该项 ~

/**
 * 单选对话框
 */
public void singleChoiceDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
 
    builder.setTitle("你现在居住地是:");
    final String[] cities = {"北京", "上海", "广州", "深圳", "杭州", "天津", "成都"};
 
    builder.setSingleChoiceItems(cities, chedkedItem, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            Toast.makeText(getApplicationContext(), "你选择了" + cities[which], Toast.LENGTH_SHORT).show();
            chedkedItem = which;
        }
    });
    builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    });
 
    builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    });
 
    AlertDialog dialog = builder.create();  //创建AlertDialog对象
    dialog.show();                           //显示对话框
}
复选对话框

复选对话框是一个可以重复选中的列表,与单选对话框有点像,不过调用的是setMultiChoiceItems方法,而且多了一个布尔值参数isChecked,表示当前点击的item是否被选中 ~

/**
 * 复选对话框
 */
public void multiChoiceDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
    builder.setTitle("请选择你喜欢的颜色:");
    final String[] colors = {"红色", "橙色", "黄色", "绿色", "蓝色", "靛色", "紫色"};
    final List<String> myColors = new ArrayList<>();
 
    builder.setMultiChoiceItems(colors, null, new DialogInterface.OnMultiChoiceClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which, boolean isChecked) {
            if (isChecked) {
                myColors.add(colors[which]);
            } else {
                myColors.remove(colors[which]);
            }
        }
    });
 
    builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            String result = "";
            for (String color : myColors) {
                result += color + "、";
            }
            Toast.makeText(getApplicationContext(), "你选择了: " + result, Toast.LENGTH_SHORT).show();
            dialog.dismiss();
        }
    });
 
    builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            myColors.clear();
            dialog.dismiss();
        }
    });
    AlertDialog dialog = builder.create();      //创建AlertDialog对象
    dialog.show();                               //显示对话框
}

进阶级

名为进阶,主要是建立在初级弹框不满足我们需求的基础下而衍生的,因为现实开发中我们的弹框内容有时候会千奇百怪,所以针对这种场景,我们需要为不同的Dialog注入不同的Layout ~

实现效果
在这里插入图片描述
实现方式

具体实现主要包含以下俩部分

  • 自定义Dialog与使用方式
  • 进出场动画的style

第一步:创建自定义Dialog继承自Dialog

package nk.com.customdialog;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.TextView;

/**
 * @author MrLiu
 * @date 2020/8/25
 * desc
 */
public class MiddleDialog extends Dialog {
    public DialogCallback mCallback;

    public MiddleDialog(@NonNull Context context, DialogCallback callback) {
        super(context);
        this.mCallback = callback;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dialog_easy);

        Window window = getWindow();
        //建议设置透明的背景色,否则部分版本效果会错乱
        window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        //弹窗布局大小
        window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        //setGravity 设置弹出位置 Gravity.BOTTOM(底部)/Gravity.CENTER(居中)
        window.setGravity(Gravity.CENTER);
        // 设置弹出动画,如需设置自己抄个出场、退场动画即可
        //window.setWindowAnimations(R.style.animate_dialog);
        //点击布局外关闭布局 false:不允许  true:允许
        setCanceledOnTouchOutside(true);
        //业务逻辑可在此dialog内实现
        TextView mSetContent = findViewById(R.id.tv_set_content);
        mSetContent.setText("dialog内的逻辑均可在我们创建的dialog中进行实现 ~");

        //确认监听
        TextView mConfirm = findViewById(R.id.tv_confirm);
        mConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCallback.onConfirm();
                //这里根据业务场景,看是否需要直接关闭弹框,也可在调用处手动关闭
                //dismiss();
            }
        });

        //取消监听
        TextView mCancel = findViewById(R.id.tv_cancel);
        mCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCallback.onCancel();
                //这里根据业务场景,看是否需要直接关闭弹框,也可在调用处手动关闭
                dismiss();
            }
        });
    }

    //确定、取消回调监听
    public interface DialogCallback {
        void onConfirm();
        void onCancel();
    }
}

dialog的layout布局 - dialog_easy

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="#ff9"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:text="兄弟啊,想你啦 ~"
        android:textColor="#fc3"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_set_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:text="控件内的布局,如无特意进行中心布局,那么我们通过window属性的Gravity控制显示位置 ~"
        android:textColor="#f98"
        android:textSize="20sp" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="right">

        <TextView
            android:id="@+id/tv_cancel"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginRight="10dp"
            android:layout_toLeftOf="@+id/tv_confirm"
            android:text="取消"
            android:textColor="#f00"
            android:textSize="20dp" />

        <TextView
            android:id="@+id/tv_confirm"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="30dp"
            android:text="确定"
            android:textColor="#f00"
            android:textSize="20dp" />
    </RelativeLayout>
</LinearLayout>

第二步:使用方式

		//R.id.btn 调用弹框的视图id - - ~
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                middleDialog = new MiddleDialog(MainActivity.this, new MiddleDialog.DialogCallback() {
                    @Override
                    public void onConfirm() {
                        Toast.makeText(MainActivity.this, "确定确定 - 上班了", Toast.LENGTH_SHORT).show();
                        middleDialog.dismiss();
                    }

                    @Override
                    public void onCancel() {
                        Toast.makeText(MainActivity.this, "取消取消 - 下班了", Toast.LENGTH_SHORT).show();
                    }
                });

                middleDialog.show();
            }
        });

扩展:抄了一个很早的最low级动画,提升用户体验…

  • 在res目录中新建anim文件夹,然后新建出入场anim_bottom_in、anim_bottom_out ~

anim_bottom_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <!--%p指相对于父容器-->
    <translate
        android:duration="600"
        android:fromYDelta="100%p" />
</set>

anim_bottom_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="600"
        android:toYDelta="100%p" />
</set>
  • animate_dialog - res→values 的style.xml加入动画的style
    <style name="animate_dialog">
        <item name="android:windowEnterAnimation">@anim/anim_bottom_in</item>
        <item name="android:windowExitAnimation">@anim/anim_bottom_out</item>
    </style>

项目级

这是我之前项目内全局常用的一个弹框,在此记录一下方便日后直接使用

在这里插入图片描述
关于自定义dialog的部分属性设置,一般都俩种方式

  • 自定义类内设置
  • 声明style,然后类内引用(这里使用此种方式)

主要分三步,创建dialog的style,创建自定义dialog,归纳方法适用多种场景 ~

第一步:添加sytle属性 - values → styles.xml

    <!--自定义dialog主题-->
    <style name="CustomDialog" parent="android:style/Theme.Dialog">
        <!--背景颜色及和透明程度-->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!--是否去除标题 -->
        <item name="android:windowNoTitle">true</item>
        <!--是否去除边框-->
        <item name="android:windowFrame">@null</item>
        <!--是否浮现在activity之上-->
        <item name="android:windowIsFloating">true</item>
        <!--是否模糊-->
        <item name="android:backgroundDimEnabled">true</item>
    </style>

第二步:自定义Dialog - CustomDialog

package nk.com.customdialog;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;

public class CustomDialog extends Dialog {
    private TextView tvTitle;
    private TextView tvMsg;
    private TextView tvCancel;
    private TextView tvConfirm;
    private String sureString, titleString, msgString, cancelStr;
    private CharSequence centerMsg, titleSS;

    private OnSureClickListener onSureClickListener;
    private OnCancelClickListener onCancelClickListener;
    private int msgColor;
    private View viewDivider;
    private int textSize;

    public CustomDialog(@NonNull Context context) {
    	//此处引用了我们上方刚写的style
        super(context, R.style.CustomDialog);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dialog_view);
        //setCanceledOnTouchOutside(false); ture:点击外部可以取消 fasle:点击外部不可取消
        //如果需要禁止系统返回键,可以采用setOnKeyListener相关方法
        initView();
        initData();
        initEvent();
    }

    private void initView() {
        tvTitle = findViewById(R.id.tv_title);
        tvMsg = findViewById(R.id.tv_msg);
        tvCancel = findViewById(R.id.tv_cancel);
        tvConfirm = findViewById(R.id.tv_confirm);
        viewDivider = findViewById(R.id.view_divider);
    }

    private void initData() {
        if (!isStringNull(sureString)) {
            tvConfirm.setText(sureString);
        }
        if (!isStringNull(titleString)) {
            tvTitle.setVisibility(View.VISIBLE);
            tvTitle.setText(titleString);
        } else {
            if (TextUtils.isEmpty(titleSS)) {
                tvTitle.setVisibility(View.GONE);
            } else {
                tvTitle.setVisibility(View.VISIBLE);
                tvTitle.setText(titleSS);
            }
        }
        if (!isStringNull(msgString)) {
            tvMsg.setText(msgString);
        } else {
            tvMsg.setText(centerMsg);
        }
        if (msgColor != 0) {
            tvMsg.setTextColor(msgColor);
        }
        if (!isStringNull(cancelStr)) {
            tvCancel.setText(cancelStr);
        }

        if (textSize > 0) {
            tvTitle.setTextSize(textSize);
        }
    }

    public void isShowConfirmButton(boolean isShow) {
        if (tvConfirm != null) {
            tvConfirm.setVisibility(isShow ? View.VISIBLE : View.GONE);
        }
        if (viewDivider != null) {
            viewDivider.setVisibility(isShow ? View.VISIBLE : View.GONE);
        }
    }

    public void isShowCancelButton(boolean isShow) {
        if (tvCancel != null) {
            tvCancel.setVisibility(isShow ? View.VISIBLE : View.GONE);
        }
        if (viewDivider != null) {
            viewDivider.setVisibility(isShow ? View.VISIBLE : View.GONE);
        }
    }

    public void setCancelText(String cancelText) {
        this.cancelStr = cancelText;
    }

    public void setTitle(String title) {
        this.titleString = title;
    }

    public void setMsgColor(int color) {
        this.msgColor = color;
    }

    public void setMsg(String msg) {
        this.msgString = msg;
    }

    public void setSureString(String sureString) {
        this.sureString = sureString;
    }

    public void setCancelGONE() {
        tvCancel.setVisibility(View.GONE);
    }

    public void setConfirmText(String mag, int color) {
        tvConfirm.setText(mag);
        tvConfirm.setTextColor(color);
    }

    public void setConfirmText(String mag) {
        this.sureString = mag;
    }

    private void initEvent() {
        tvCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (onCancelClickListener != null) {
                    onCancelClickListener.cancelClick();
                }
                CustomDialog.this.dismiss();
            }
        });
        tvConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (onSureClickListener != null) {
                    onSureClickListener.sureClick();
                    CustomDialog.this.dismiss();
                }
            }
        });
    }

    /**
     * 设置确定按钮和取消被点击的接口
     */
    public interface OnSureClickListener {
        void sureClick();
    }

    public interface OnCancelClickListener {
        void cancelClick();
    }

    /**
     * 设置取消按钮的显示内容和监听
     */
    public void setNoOnclickListener(OnCancelClickListener onCancelClickListener) {
        this.onCancelClickListener = onCancelClickListener;
    }

    /**
     * 设置确定按钮的显示内容和监听
     */
    public void setOnSureClickListener(OnSureClickListener onSureClickListener) {
        this.onSureClickListener = onSureClickListener;
    }

    public void setCenterMsg(CharSequence centerMsg) {
        this.centerMsg = centerMsg;
    }

    public CharSequence getCenterMsg() {
        return centerMsg;
    }

    public void setTitleSS(CharSequence titleSS) {
        this.titleSS = titleSS;
    }

    public CharSequence getTitleSS() {
        return titleSS;
    }

    public void setTextSize(int textSize) {
        this.textSize = textSize;
    }

    public int getTextSize() {
        return textSize;
    }

    /**
     * 判断字符串是否为null的方法
     */
    public static boolean isStringNull(String str) {
        return str == null || "".equals(str) || " ".equals(str) || "[]".equals(str) || str.length() == 0;
    }

}

第三步:方法归纳 - DialogUtil

package nk.com.customdialog;

import android.content.Context;
import android.support.v4.content.ContextCompat;


public class DialogUtil {

    /**
     * 方法重载,适用多种场景
     */
    public static void showDialog(Context context, String msg, CustomDialog.OnSureClickListener onSureClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setMsg(msg);
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.show();
    }

    public static void showDialog(Context context, String title, String msg, CustomDialog.OnSureClickListener onSureClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setMsg(msg);
        customDialog.setTitle(title);
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.show();
    }

    public static void showDialog(Context context, String msg, int color, CustomDialog.OnSureClickListener onSureClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setMsg(msg);
        customDialog.setMsgColor(ContextCompat.getColor(context, color));
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.show();
    }

    public static void showDialog(Context context, String title, String msg, int color, CustomDialog.OnSureClickListener onSureClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setTitle(title);
        customDialog.setMsg(msg);
        customDialog.setMsgColor(ContextCompat.getColor(context, color));
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.show();
    }

    public static void showDialog(Context context, String msg, String cancel, String confirm, CustomDialog.OnSureClickListener onSureClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setMsg(msg);
        customDialog.setSureString(confirm);
        customDialog.setCancelText(cancel);
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.show();
    }

    public static void showDialog(Context context, String msg, String cancel, String confirm, CustomDialog.OnSureClickListener onSureClickListener, CustomDialog.OnCancelClickListener onCancelClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setMsg(msg);
        customDialog.setSureString(confirm);
        customDialog.setCancelText(cancel);
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.setNoOnclickListener(onCancelClickListener);
        customDialog.show();
    }

    public static void showDialog(Context context, String title, String msg, String confirm, String cancelText, CustomDialog.OnSureClickListener onSureClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setTitle(title);
        customDialog.setMsg(msg);
        customDialog.setConfirmText(confirm);
        customDialog.setCancelText(cancelText);
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.show();
    }

    public static void showDialog(Context context, String title, String msg, String confirm, String cancelText, CustomDialog.OnSureClickListener onSureClickListener, CustomDialog.OnCancelClickListener onCancelClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setTitle(title);
        customDialog.setMsg(msg);
        customDialog.setConfirmText(confirm);
        customDialog.setCancelText(cancelText);
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.setNoOnclickListener(onCancelClickListener);
        customDialog.show();
    }

    public static void showDialog(Context context, String title, String msg, String confirm, String cancelText, boolean isShowConfirm, boolean isShowCancel, CustomDialog.OnSureClickListener onSureClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setTitle(title);
        customDialog.setMsg(msg);
        customDialog.isShowConfirmButton(isShowConfirm);
        customDialog.isShowCancelButton(isShowCancel);
        customDialog.setConfirmText(confirm);
        customDialog.setCancelText(cancelText);
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.show();
    }

    public static void showDialog(int textize, Context context, CharSequence title, String msg, String confirm, String cancelText, boolean isShowConfirm, boolean isShowCancel, CustomDialog.OnSureClickListener onSureClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setTitleSS(title);
        customDialog.setMsg(msg);
        customDialog.isShowConfirmButton(isShowConfirm);
        customDialog.isShowCancelButton(isShowCancel);
        customDialog.setConfirmText(confirm);
        customDialog.setCancelText(cancelText);
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.setTextSize(textize);
        customDialog.show();
    }

    public static void showDialog(Context context, CharSequence msg, String cancel, String confirm, CustomDialog.OnSureClickListener onSureClickListener) {
        CustomDialog customDialog = new CustomDialog(context);
        customDialog.setCenterMsg(msg);
        customDialog.setSureString(confirm);
        customDialog.setCancelText(cancel);
        customDialog.setOnSureClickListener(onSureClickListener);
        customDialog.show();
    }
}

常见问题

Dialog 无透明效果||透明效果呈暗灰色||布局错乱效果

dialog的xml 无透明效果||透明效果呈暗灰色||布局错乱

解决方式:将此Dialog设置以下属性

Dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

Dialog.getWindow().setBackgroundDrawable(new ColorDrawable());
Dialog 弹出框不居中

这里指的是当我们的Dialog框弹出后,未置于屏幕的正中间(部分机型会跑到屏幕顶部)

关于Dialog不居中的场景有俩种,一种是常规的Dialog,一种是自定义布局的Dialog

  • 首先设置Dialog的gravity属性为center,如无效继续往下看
  • 如果你是自定义Dialog,且Dialog布局整体设置,那么你需要仔细看一下自己的布局是否有问题 ~
  • 如以上都没有解决你的问题,那么使用下方的这种通配方式吧

在Dialog调用 show()方法后,调用以下方法 ~

    /**
     * 设置Dialog于屏幕正中间
     */
    void setLocation(Dialog dialog) {
        //放在show()之后,不然有些属性是没有效果的,比如height和width
        Window dialogWindow = dialog.getWindow();
        WindowManager m = context.getWindowManager();
        // 获取屏幕宽、高
        Display d = m.getDefaultDisplay();
        // 获取对话框当前的参数值
        WindowManager.LayoutParams p = dialogWindow.getAttributes(); 
        // 设置宽度 - 宽度设置为屏幕的0.95
        p.width = (int) (d.getWidth() * 0.95);
        //设置显示位置
        p.gravity = Gravity.CENTER;
        //设置透明度
        //p.alpha = 0.8f;
        dialogWindow.setAttributes(p);
    }

整体代码

    public void upgradeDialog(String currentName) {
    	//这里我的弹框属性是封装包Dialog的Style中的,下方已记录
        AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.BasicDialogStyle);
        AlertDialog alertDialog = builder.setMessage("当前版本:" + currentName + ",发现新版本")
                .setPositiveButton("立即更新", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        downloadApk(basicUrl);
                    }
                })
                .setNeutralButton("以后再说", null)
                .create();
        alertDialog.show();
        
        //放在show()之后,不然有些属性是没有效果的,比如height和width
        Window dialogWindow = alertDialog.getWindow();
        //context指向Activity,不然调用不到getWindowManager()方法
        WindowManager m = context.getWindowManager();
        // 获取屏幕宽、高
        Display d = m.getDefaultDisplay();
        // 获取对话框当前的参数值
        WindowManager.LayoutParams p = dialogWindow.getAttributes();
        // 设置宽度 - 宽度设置为屏幕的0.95
        p.width = (int) (d.getWidth() * 0.95);
        //设置显示位置
        p.gravity = Gravity.CENTER;
        //设置透明度
        //p.alpha = 0.8f;
        dialogWindow.setAttributes(p);
    }

BasicDialogStyle

    <!-- 自定义弹出样式 -->
    <style name="BasicDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
        <!--居中位置-->
        <item name="android:gravity">center</item>
        <!--是否浮在窗口之上-->
        <item name="android:windowIsFloating">true</item>
        <!--半透明-->
        <item name="android:windowIsTranslucent">true</item>
        <!--是否显示title-->
        <item name="android:windowNoTitle">true</item>
        <!--dialog之外没有焦点的区域是否罩上黑色半透明-->
        <item name="android:background">#fff</item>
        <!--        <item name="android:textColor">@color/gray</item>-->
        <!-- 这里是修改内容区域背景颜色 -->
        <item name="android:layout_gravity">center</item>
        <!--        <item name="android:textColorPrimary">#ff2</item>-->
        <item name="buttonBarPositiveButtonStyle">?attr/buttonBarButtonStyle</item>
        <item name="buttonBarNegativeButtonStyle">?attr/buttonBarButtonStyle</item>
    </style>
Dialog 原始框太丑,优化字体颜色、背景等

记录这个问题点的场景是Dialog原始效果在Andoird9.0显示效果还行,但是相同代码用在部分Andoird6.0之前的机器时,Dialog效果就非常之丑,而且有的设置属性还无效

解决方式有俩种,具体区别已在对应方式下进行了说明

方式一

根据这种方式设置Dialog后,解决了版本兼容适配问题,效果看起来还ok ~

  • 创建专属DialogStyle
    <!-- 自定义弹出样式 -->
    <style name="BasicDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
        <!--居中位置-->
        <item name="android:gravity">center</item>
        <!--是否浮在窗口之上-->
        <item name="android:windowIsFloating">true</item>
        <!--半透明-->
        <item name="android:windowIsTranslucent">true</item>
        <!--是否显示title-->
        <item name="android:windowNoTitle">true</item>
        <!--dialog之外没有焦点的区域是否罩上黑色半透明-->
        <item name="android:background">#fff</item>
        <!--        <item name="android:textColor">@color/gray</item>-->
        <!-- 这里是修改内容区域背景颜色 -->
        <item name="android:layout_gravity">center</item>
        <!--        <item name="android:textColorPrimary">#ff2</item>-->
        <!--重写按钮颜色-->
        <item name="buttonBarPositiveButtonStyle">?attr/buttonBarButtonStyle</item>
        <item name="buttonBarNegativeButtonStyle">?attr/buttonBarButtonStyle</item>
        <item name="buttonBarNeutralButtonStyle">?attr/buttonBarButtonStyle</item>
    </style>
  • 使用时,传入上方Dialog样式
  AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.BasicDialogStyle);

方式二

根据这种方式设置之后,Dialog的扩展效果更多一些,可自由设置按钮的颜色 ~

  • style文件内重写按钮的style
    <!--确定按钮样式-->
    <style name="positiveBtnStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
        <item name="android:textColor">#0000ff</item>
    </style>

    <!--取消按钮样式-->
    <style name="negativeBtnStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
        <item name="android:textColor">#999999</item>
    </style>
  • 找到AndroidMainfest内的theme绑定样式
    在这里插入图片描述
  • style文件内将之前按键的style加入到theme绑定的style内,整体如下
    这里的Theme.Tmp相当于整个为app设置的一个style,这样设置后每个Dialog自动会使用Theme.Tmp内设置的Dialog按钮颜色
<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.Tmp" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->

        <item name="buttonBarPositiveButtonStyle">@style/positiveBtnStyle</item>
        <item name="buttonBarNegativeButtonStyle">@style/negativeBtnStyle</item>
    </style>

    <!--确定按钮样式-->
    <style name="positiveBtnStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
        <item name="android:textColor">#0000ff</item>
    </style>

    <!--取消按钮样式-->
    <style name="negativeBtnStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
        <item name="android:textColor">#999999</item>
    </style>

</resources>
Dialog 屏幕背景亮度调试

设置屏幕背景变暗

private void setScreenBgDarken() {
    WindowManager.LayoutParams lp = getWindow().getAttributes();
    lp.alpha = 0.5f;
    lp.dimAmount = 0.5f;
    getWindow().setAttributes(lp);
}

设置屏幕背景变亮

private void setScreenBgLight() {
    WindowManager.LayoutParams lp = getWindow().getAttributes();
    lp.alpha = 1.0f;
    lp.dimAmount = 1.0f;
    getWindow().setAttributes(lp);
}
Dialog 弹出时隐藏状态栏、导航栏

dialog弹出时自动显示顶部状态栏与底部导航栏,需求为不显示相关状态栏

我们的app是全屏沉浸式的,发现activity在设置了全屏后,弹出dialog底部会跳出导航栏虚拟键。具体原因是因为Dialog的Window抢走了焦点,Window 中的 DecorView 状态改变导致了退出。

   /**
     * 是否重写此show方法,建立在你是否需要隐藏顶部&底部状态栏,如有此需求则重写,如无此需求则删除以下代码
    * */
  @Override
  public void show() {
    this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
    super.show();
    fullScreenImmersive(getWindow().getDecorView());
    this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
  }
  
private void fullScreenImmersive(View view) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        | View.SYSTEM_UI_FLAG_FULLSCREEN;
      view.setSystemUiVisibility(uiOptions);
    }
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

远方那座山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值