用过Android的默认对话框的都懂,不管是哪个版本的对话框,都丑到爆!就算是Google推崇的Material Design风格的弹窗一样不好看,基本每款APP都不会去使用默认的对话框样式,他们都有自己的风格,怎样去改变默认的对话框样式呢?只能自定义了,将系统对话框改为自己喜欢或者是APP特有风格的样式。本文将介绍如何去实现自定义Dialog,仿IOS,并添加动画效果,并提供丰富的方法调用,让开发者可以在已有样式的基础上进行进一步的细节改变。算是一个工具类了,直接copy就可以直接用了。
原创文章,转载请注明出处:https://blog.youkuaiyun.com/Lone1yCode/article/details/79927873
一、举例
这是Android 4.2版本的弹窗:
这是Android 7.0版本的弹窗:
我是没有觉得很好看。大概这就是程序员的审美吧。
下面再看一下IOS的对话框,话说找这个对话框太难了。我找了好久好久,都找不到有什么地方能弹窗,不找的时候一直有。还好不负所望,找了俩。中间弹窗对话框:
IOS底部弹窗:
是不是感觉还不错!Android的系统对话框虽然样式很丑,但毕竟是开源系统,它可以轻松实现对话框样式的自定义,而且Android的对话框的样式基本一个APP就一个样,种类繁多,样式丰富。
二、实现效果
经过自定义后,现在的Dialog已经能实现各种丰富的样式了。
可以看到自定义的Dialog已经实现了IOS效果的弹窗。并且里面的按钮、文本、标题都可以在使用时进行各种详细的定义,如改变文字颜色、文字大小、文字粗体、背景色,还可以传入自己定义的动画效果去替换原有的动画效果,如果不觉得突兀,还可以取消动画效果。
三、特点
其实特点就是仿照IOS的特点。
1、圆角。经过自定义的弹窗,其圆角效果已经和IOS的很接近了,而且圆角很大,当然如果你不喜欢,可以在XML文件中进行修改,目前的圆角是15。
2、Dialog控件之间的间隔很大。这应该也算是IOS风格的一个特色了,它的文字、留白都非常大,如果说多数Android的弹窗效果都是小巧玲珑的话,这种风格可以说是豪迈奔放了。
3、动画效果。这个动画效果是完全仿IOS的,底部弹窗效果不是很像,只是加了一个平移效果。中间弹窗的话还能算是精仿,包括缩放和透明度的变化。
四、全部代码
说实话,全部代码并不长,只是注释太多,占用了绝大部分的空间。
1、MyDialog核心类
package com.my.dialogdemo;
import android.app.Dialog;
import android.content.Context;
import android.support.v7.app.ActionBar;
import android.text.TextPaint;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static android.content.ContentValues.TAG;
public class MyDialog {
private Context mContext; //上下文
private View mDialogLayout; //弹窗布局
private boolean mCancelable = true; //返回键、窗体外区域是否可点击取消,默认可以
private View.OnClickListener positiveButton; //positive区域监听器
private View.OnClickListener negativeButton; //negative区域监听器
private AdapterView.OnItemClickListener mItemClickListener; //item的点击事件
private Dialog dialog; //构建的弹窗
private int mCustomAnim; //自定义动画
private boolean mIsShowTitle; //是否显示标题,默认不显示
private boolean mIsShowNegativeButton; //是否显示negative区域按钮,默认不显示
private boolean mIsShowPositiveButton; //是否显示positive区域按钮,默认不显示
private boolean mIsShowListView; //是否在内容区显示ListView,默认不显示
private boolean mIsHaveCustomAnim; //是否含有自定义的动画效果
private boolean mIsShowBottomTitle; //是否显示底部弹窗标题,默认不显示
private boolean mIsShowBottomNegativeButton; //是否显示底部弹窗的negative区域按钮,默认不显示
private boolean mIsBottomDialog; //是否是底部弹窗,默认中间弹窗
private MyAdapter mAdapter; //Adapter,设配自定义的数据
private List<StringItemBean> mDataList; //数据源,显示的文本
public static final String BOTTOM = "BOTTOM"; //底部弹窗标志
/**
* 中间弹窗,构造函数
*
* @param context 上下文
*/
public MyDialog(Context context) {
this.mContext = context;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDialogLayout = inflater.inflate(R.layout.my_custom_dialog_layout, null);
}
/**
* 中间弹窗,构造函数,需要传入自定义动画的ID,若传入0,则代表无动画
*
* @param context 上下文
* @param customAnim 自定义的动画效果ID
*/
public MyDialog(Context context, int customAnim) {
this(context);
mCustomAnim = customAnim;
mIsHaveCustomAnim = true;
}
/**
* 底部弹窗,构造函数,需要传入String类型参数,BOTTOM,才会显示底部Dialog
*
* @param context 上下文
* @param gravity 位置,String类型,必须是"BOTTOM"才会显示底部Dialog
*/
public MyDialog(Context context, String gravity) {
this.mContext = context;
if (gravity.equals(BOTTOM)) {
mIsBottomDialog = true;
}
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDialogLayout = inflater.inflate(R.layout.my_custom_bottom_dialog_layout, null);
}
/**
* 都不弹窗,构造函数,需要传入String类型参数,BOTTOM,才会显示底部Dialog;自定义动画效果
*
* @param context 上下文
* @param customAnim 自定义的动画效果
* @param gravity 位置,String类型,必须是"BOTTOM"才会显示底部Dialog
*/
public MyDialog(Context context, int customAnim, String gravity) {
this.mContext = context;
if (gravity.equals(BOTTOM)) {
mIsBottomDialog = true;
}
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDialogLayout = inflater.inflate(R.layout.my_custom_bottom_dialog_layout, null);
mCustomAnim = customAnim;
mIsHaveCustomAnim = true;
}
/**
* 能否返回键取消和点击弹窗外部区域取消
* 中间、底部弹窗共用
*
* @param boolean1 true 代表可以取消,false 不可取消
* @return this
*/
public MyDialog setCancelable(Boolean boolean1) {
this.mCancelable = boolean1;
return this;
}
/**
* 中间弹窗,设置标题 int型 不常用,适配更多类型可重载多个该方法,参数类型不同即可
*
* @param title int型参数
* @return this
*/
public MyDialog setTitle(int title) {
mIsShowTitle = true;
((TextView) mDialogLayout.findViewById(R.id.title)).setText(title);
return this;
}
/**
* 中间弹窗,设置标题 String型 最常用
*
* @param title String型参数
* @return this
*/
public MyDialog setTitle(String title) {
mIsShowTitle = true;
((TextView) mDialogLayout.findViewById(R.id.title)).setText(title);
return this;
}
/**
* 中间弹窗,设置标题文字大小
*
* @param size 大小值,int型
* @return this
*/
public MyDialog setTitleSize(int size) {
((TextView) mDialogLayout.findViewById(R.id.title)).setTextSize(size);
return this;
}
/**
* 中间弹窗,设置标题文字颜色
*
* @param color 颜色
* @return this
*/
public MyDialog setTitleColor(int color) {
((TextView) mDialogLayout.findViewById(R.id.title)).setTextColor(mContext.getResources().getColor(color));
return this;
}
/**
* 中间弹窗,设置标题字体为粗体
*
* @return this
*/
public MyDialog setTitleStyleBold(){
TextView tv = (TextView)mDialogLayout.findViewById(R.id.title);
TextPaint tp = tv.getPaint();
tp.setFakeBoldText(true);
return this;
}
/**
* 中间弹窗,设置标题区域的背景颜色 不常用
*
* @param color 颜色
* @return this
*/
public MyDialog setTitleBackgroundColor(int color) {
mDialogLayout.findViewById(R.id.title_background).setBackgroundColor(mContext.getResources().getColor(color));
return this;
}
/**
* 中间弹窗,设置内容,int型,不常用,适配更多类型可重载多个该方法,参数类型不同即可
*
* @param message int型参数
* @return this
*/
public MyDialog setMessage(int message) {
((TextView) mDialogLayout.findViewById(R.id.message)).setText(message);
return this;
}
/**
* 中间弹窗,设置内容,String型,最常用
*
* @param message String型信息
* @return this
*/
public MyDialog setMessage(String message) {
((TextView) mDialogLayout.findViewById(R.id.message)).setText(message);
return this;
}
/**
* 中间弹窗,设置内容的文本颜色
*
* @param color 文本颜色
* @return this
*/
public MyDialog setMessageColor(int color){
((TextView) mDialogLayout.findViewById(R.id.message)).setTextColor(
mContext.getResources().getColor(color));
return this;
}
/**
* 中间弹窗,设置内容区域的背景色
*
* @param color 背景色
* @return this
*/
public MyDialog setMessageBackground(int color){
mDialogLayout.findViewById(R.id.content).setBackgroundColor(
mContext.getResources().getColor(color));
return this;
}
/**
* 中间弹窗,设置negative区域的文本和点击事件,一般为"取消"
* 同AlertDialog.Builder的设置名称相同
*
* @param negativeText 按钮文本
* @param listener 监听器
* @return this
*/
public MyDialog setNegativeButton(String negativeText, View.OnClickListener listener) {
mIsShowNegativeButton = true;
((TextView) mDialogLayout.findViewById(R.id.negative)).setText(negativeText);
this.negativeButton = listener;
return this;
}
/**
* 中间弹窗,设置negative区域显示文本的颜色,如蓝色的"取消"文字
* 多数APP如网购APP,在某个商品浏览页面,不希望用户退出又必须要给出退出提示时,多将negative设置为显眼的颜色
* 而positive设置为暗色。所以该方法还是使用比较常见的
*
* @param color 颜色
* @return this
*/
public MyDialog setNegativeButtonColor(int color) {
((TextView) mDialogLayout.findViewById(R.id.negative)).setTextColor(
mContext.getResources().getColor(color));
return this;
}
/**
* 中间弹窗,设置negative文本的大小
*
* @param size 文本大小
* @return this
*/
public MyDialog setNegativeButtonTextSize(int size){
((TextView) mDialogLayout.findViewById(R.id.negative)).setTextSize(size);
return this;
}
/**
* 中间弹窗,设置negative文本字体为粗体
*
* @return this
*/
public MyDialog setNegativeButtonStyleBold(){
TextView tv = (TextView) mDialogLayout.findViewById(R.id.negative);
TextPaint tp = tv.getPaint();
tp.setFakeBoldText(true);
return this;
}
/**
* 中间弹窗,设置positive区域的文本和点击事件,一般为"确定"
* 同AlertDialog.Builder的设置名称相同
*
* @param positiveText 按钮文本
* @param listener 监听器
* @return this
*/
public MyDialog setPositiveButton(String positiveText, View.OnClickListener listener) {
mIsShowPositiveButton = true;
((TextView) mDialogLayout.findViewById(R.id.positive)).setText(positiveText);
this.positiveButton = listener;
return this;
}
/**
* 中间弹窗,设置positive区域显示文本的颜色,如蓝色的"确定"文字
*
* @param color 颜色
* @return this
*/
public MyDialog setPositiveButtonColor(int color) {
((TextView) mDialogLayout.findViewById(R.id.positive)).setTextColor(
mContext.getResources().getColor(color));
return this;
}
/**
* 中间弹窗,设置positive区域显示文本的大小
*
* @param size 文本大小
* @return this
*/
public MyDialog setPositiveButtonSize(int size){
((TextView) mDialogLayout.findViewById(R.id.positive)).setTextSize(size);
return this;
}
/**
* 中间弹窗,设置positive文本字体为粗体
*
* @return this
*/
public MyDialog setPositiveButtonStyleBold(){
TextView tv = (TextView) mDialogLayout.findViewById(R.id.