Android 使用Builder设计模式打造通用的Dialog
2017-12-27 本文已影响237人
Sky_Blue
一、Builder设计模式的定义
将一个复杂对象的构建和它的表现分离,使得同样的构建过程,可以创建不同的表示。
二、Android使用系统的Dialog
//1.得到对话框的构造器,可以构造对话的模版
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("标题");
builder.setMessage("包含内容");
//2.添加一个确定按钮
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
//3.添加一个取消按钮
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
//4.使用构造器创建一个对话框的对象
AlertDialog dialog = builder.create();
//5.显示对话框
dialog.show();
三、安际开发情况
由于每个APP的风格不一样,UI设计的弹窗五花八门,系统的Dialog用得不多。系统的Dialog定制性不强等等。
由于系统的Dialog有诸多的不便,自己写一个通用的可定制的Dialog就是必要的了。
四、Dialog都有哪些通用特性?
1.Dialog的显示动画、位置,常用的是由下面出来和中间出来。
2.Dialog的背景,包括背景色、背景圆角。
3.其它的一些设置,用Dialog系统有的就行了,比如取消监听等等
五、Dialog的Builder控制建造类,主要是设置Dialog构建的一些参数。
/**
* Dialog的Builder控制建造类
*/
public class QuickBuilder {
private QuickDialog mDialog;
public boolean mCancelable = true;
public DialogInterface.OnCancelListener mOnCancelListener;
public DialogInterface.OnDismissListener mOnDismissListener;
public DialogInterface.OnKeyListener mOnKeyListener;
/**
* Dialog的View 与Dialog的布局ID 设置一个即可
*/
public View mView;
/**
* Dialog的View 与Dialog的布局ID 设置一个即可
*/
public int mViewLayoutResId;
/**
* 存放文本的集合
*/
public SparseArray<CharSequence> mTextArray = new SparseArray<>();
/**
* 存放点击事件的集合
*/
public SparseArray<View.OnClickListener> mClickArray = new SparseArray<>();
/**
* 宽,默认是屏幕的宽
*/
public int mWidth;
public int mHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
/**
* 显示位置
*/
public int mGravity = Gravity.CENTER;
/**
* 显示动画
*/
public int mAnimation;
/**
* 宽,默认缩放
*/
public float mScale = 0.85f;
/**
* 背景圆角,默认5
*/
public int mBgRadius = 5;
/**
* 背景色,默认白色
*/
public int mBgColor = Color.parseColor("#ffffffff");
/**
* 是否模糊
*/
public boolean isDimEnabled = true;
private QuickBuilder(Context context, int themeResId) {
DisplayMetrics dm = context.getResources().getDisplayMetrics();
mWidth = dm.widthPixels;
this.mDialog = new QuickDialog(context, themeResId);
}
private QuickBuilder(Context context) {
// 默认主题,在style配置,下面给出
this(context, R.style.Theme_Dialog);
}
public static QuickBuilder create(Context context, int themeResId) {
return new QuickBuilder(context, themeResId);
}
public static QuickBuilder create(Context context) {
return new QuickBuilder(context);
}
public QuickBuilder setText(int viewId, CharSequence text) {
mTextArray.put(viewId, text);
return this;
}
public QuickBuilder setOnClickListener(int viewId, View.OnClickListener onClickListener) {
mClickArray.put(viewId, onClickListener);
return this;
}
/**
* 设置显示的View
*/
public QuickBuilder setContentView(int layoutResId) {
mView = null;
mViewLayoutResId = layoutResId;
return this;
}
/**
* 设置显示的布局
*/
public QuickBuilder setContentView(View view) {
mView = view;
mViewLayoutResId = 0;
return this;
}
/**
* 设置ContentView背景的颜色:默认白色
*/
public QuickBuilder setContentViewBgColor(int resId) {
mBgColor = resId;
return this;
}
/**
* 设置ContentView背景的圆角:默认10dp
*
* @param radus 内部已转成dp
* @return
*/
public QuickBuilder setContentViewBgRadius(int radus) {
mBgRadius = radus;
return this;
}
/**
* 设置背景是否模糊:默认是模糊的
*
* @param isDimEnabled
* @return
*/
public QuickBuilder setIsDimEnabled(boolean isDimEnabled) {
this.isDimEnabled = isDimEnabled;
return this;
}
/**
* 设置宽度占满的比例
*/
public QuickBuilder setWidthScale(float scale) {
mScale = scale;
return this;
}
public QuickBuilder fullWidth() {
mScale = 1.0f;
return this;
}
public QuickBuilder fromBottom(boolean isAnim) {
if (isAnim) {
mAnimation = R.style.Anim_Dialog_Bottom;
}
mGravity = Gravity.BOTTOM;
return this;
}
public QuickBuilder setAnimation(int resId) {
mAnimation = resId;
return this;
}
public QuickBuilder setWidth(int width) {
mWidth = width;
return this;
}
public QuickBuilder setHeight(int height) {
mHeight = height;
return this;
}
/**
* 设置点击空白是否消失
*/
public QuickBuilder setCancelable(boolean cancelable) {
mCancelable = cancelable;
return this;
}
/**
* 设置取消的监听
*/
public QuickBuilder setOnCancelListener(DialogInterface.OnCancelListener onCancelListener) {
mOnCancelListener = onCancelListener;
return this;
}
/**
* 设置Dialog消息的监听
*/
public QuickBuilder setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) {
mOnDismissListener = onDismissListener;
return this;
}
/**
* 设置按键的监听
*/
public QuickBuilder setOnKeyListener(DialogInterface.OnKeyListener onKeyListener) {
mOnKeyListener = onKeyListener;
return this;
}
public QuickDialog create() {
mDialog.apply(this);
return mDialog;
}
public QuickDialog show() {
QuickDialog dialog = create();
dialog.show();
return dialog;
}
}
六、Dialog View显示的辅助类,主要是加载View布局和找到里面的View等
/**
* Dialog View显示的辅助类
*/
public class ViewHelper {
/**
* Dialog显示的View
*/
private View mContentView;
private SparseArray<WeakReference<View>> mViews = new SparseArray<>();
public ViewHelper(Context context, int layoutResId) {
mContentView = LayoutInflater.from(context).inflate(layoutResId, null);
}
public ViewHelper(View mView) {
mContentView = mView;
}
public View getContentView() {
return mContentView;
}
/**
* 设置文本
*/
public void setText(int viewId, CharSequence charSequence) {
TextView tv = getView(viewId);
if (tv != null && charSequence != null) {
tv.setText(charSequence);
}
}
public <T extends View> T getView(int viewId) {
WeakReference<View> viewWeakReference = mViews.get(viewId);
View view = null;
if (viewWeakReference == null) {
view = mContentView.findViewById(viewId);
if (view != null) {
mViews.put(viewId, new WeakReference<>(view));
}
} else {
view = viewWeakReference.get();
}
return (T) view;
}
/**
* 设置点击事件
*/
public void setOnClickListener(int viewId, View.OnClickListener onClickListener) {
View view = getView(viewId);
if (view != null && onClickListener != null) {
view.setOnClickListener(onClickListener);
}
}
}
六、自定义通用的Dialog
/**
* 自定义通用的Dialog
*/
public class QuickDialog extends Dialog {
private ViewHelper mViewHelper = null;
public QuickDialog(@NonNull Context context, @StyleRes int themeResId) {
super(context, themeResId);
}
/**
* 绑定和设置参数
*/
public QuickDialog apply(QuickBuilder params) {
// 1.设置布局
mViewHelper = null;
if (params.mViewLayoutResId != 0) {
mViewHelper = new ViewHelper(getContext(), params.mViewLayoutResId);
}
if (params.mView != null) {
mViewHelper = new ViewHelper(params.mView);
}
if (mViewHelper == null) {
throw new IllegalArgumentException("请调用setContentView方法设置布局");
}
// 创建前景和圆角
final GradientDrawable bg = new GradientDrawable();
float radius = dp2px(params.mBgRadius);
bg.setCornerRadii(new float[]{radius, radius, radius, radius, radius, radius, radius, radius});// 1 2 3 4(顺时针)
bg.setColor(params.mBgColor);
// 设置背景
View contentView = mViewHelper.getContentView();
// 设置Dialog的布局
setContentView(contentView);
// 设置背景
contentView.setBackgroundDrawable(bg);
// 是否可以取消
setCancelable(params.mCancelable);
// 设置监听
if (params.mOnCancelListener != null) {
setOnCancelListener(params.mOnCancelListener);
}
if (params.mOnDismissListener != null) {
setOnDismissListener(params.mOnDismissListener);
}
if (params.mOnKeyListener != null) {
setOnKeyListener(params.mOnKeyListener);
}
Window window = getWindow();
// 显示的位置
window.setGravity(params.mGravity);
// 动画
if (params.mAnimation != 0) {
window.setWindowAnimations(params.mAnimation);
}
// 宽高
WindowManager.LayoutParams windowAttributes = window.getAttributes();
windowAttributes.width = (int) (params.mWidth * params.mScale);
windowAttributes.height = params.mHeight;
window.setAttributes(windowAttributes);
// 设置背景是否模糊
if (!params.isDimEnabled) {
window.setDimAmount(0f);
}
// 设置文本
int textSize = params.mTextArray.size();
for (int i = 0; i < textSize; i++) {
mViewHelper.setText(params.mTextArray.keyAt(i), params.mTextArray.valueAt(i));
}
// 设置点击
int clickSize = params.mClickArray.size();
for (int i = 0; i < clickSize; i++) {
mViewHelper.setOnClickListener(params.mClickArray.keyAt(i), params.mClickArray.valueAt(i));
}
return this;
}
public int dp2px(float dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
}
public void setText(int viewId, CharSequence text) {
mViewHelper.setText(viewId, text);
}
public void setOnClickListener(int viewId, View.OnClickListener onClickListener) {
mViewHelper.setOnClickListener(viewId, onClickListener);
}
public <T extends View> T getView(int viewId) {
return mViewHelper.getView(viewId);
}
}
七、Dialog默认显示的主题
<!--从下弹出来的基本动画-->
<style name="Anim_Dialog_Bottom" parent="@style/Theme.AppCompat.Dialog">
<item name="android:windowEnterAnimation">@anim/slide_in</item>
<item name="android:windowExitAnimation">@anim/slide_out</item>
</style>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!--slide_in-->
<translate
android:duration="250"
android:fromXDelta="0"
android:fromYDelta="100%"
android:toXDelta="0"
android:toYDelta="0" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!--slide_out-->
<translate
android:duration="250"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="100%" />
</set>
八、Dialog的使用
QuickDialog dialog = QuickBuilder.create(this)
.setContentView(R.layout.dialog_loading)
.fromBottom(true)
.setCancelable(false)
.setIsDimEnabled(false)
.create();
// 设置Dialog布局里面View的点击事件,文本设置一样
dialog.setOnClickListener(R.id.dialog_message, new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
dialog.show();
用起来感觉简单多了,也可以根据UI定制一些APP通用的Dialog。