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