Android初级教程 - Dialog的日常使用

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

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

入门级

关于一般的入门级可以通过这篇Blog简单看下,我这里只记录一些简单的使用 ~

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

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);

在这里插入图片描述

扫描二维码关注公众号,回复: 12913617 查看本文章

示范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();
    }

进阶级

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

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

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

关于自定义dialog的部分属性设置,一般都俩种方式

  • 自定义类内设置(这里使用此种方式)
  • 声明style,然后类内引用
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的xml 无透明效果||透明效果呈暗灰色||布局错乱

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

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

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

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);
    }
  }

猜你喜欢

转载自blog.csdn.net/qq_20451879/article/details/108224502