因为项目中常用到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);
示范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);
}
}