您的位置:首页 > 产品设计 > UI/UE

Builder模式打造通用Dialog效果

2018-03-08 07:45 375 查看

这是参照系统Dialog,采用Builder模式实现的一个万能dialog效果;
参照系统dialog的方式,涉及到AlertDialog、DialogViewHelper、AlertController这三个类,AlertDialog类中主要提供了一些dialog样式、效果、布局等设置的方法,采用Builder的设计模式,在使用的时候可以采用链式调用;
package com.dialogdemo.dialog;

import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;

import com.dialogdemo.R;

/**
* Created by Administrator on 2017/5/21.
* 自定义dialog
*/

public class AlertDialog extends Dialog {
private AlertController mAlert;

public AlertDialog(Context context, int themeResId) {
super(context, themeResId);
mAlert = new AlertController(this, getWindow());
}

/**
* 设置文本
*
* @param viewid
* @param text
*/
public void setText(int viewid, CharSequence text) {
mAlert.setText(viewid, text);
}

public <T extends View> T getView(int viewid) {
return mAlert.getView(viewid);
}

/**
* 设置点击
*
* @param viewid
* @param listener
*/
public void setOnClickListener(int viewid, View.OnClickListener listener) {
mAlert.setOnClickListener(viewid, listener);
}

public static class Builder {
private AlertController.AlertParams P;

public Builder(Context context) {
this(context, R.style.dialog);//默认样式
}

public Builder(Context context, int themeResId) {
P = new AlertController.AlertParams(context, themeResId);
}

public AlertDialog create() {
final AlertDialog dialog = new AlertDialog(P.mContext, P.mThemeResId);
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(P.mOnCancelListener);
dialog.setOnDismissListener(P.mOnDismissListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
}
return dialog;
}

/**
* 设置布局
*
* @param v
* @return
*/
public Builder setContentView(View v) {
P.mView = v;
P.mViewLayoutResId = 0;
return this;
}

/**
* 设置布局
*
* @param layoutId
* @return
*/
public Builder setContentView(int layoutId) {
P.mView = null;
P.mViewLayoutResId = layoutId;
return this;
}

/**
* 设置文本
*
* @param viewId
* @param text
* @return
*/
public Builder setText(int viewId, CharSequence text) {
P.mTextArray.put(viewId, text);
return this;
}

/**
* 设置点击
*
* @param view
* @param listener
* @return
*/
public Builder setOnClickListener(int view, View.OnClickListener listener) {
P.mClickArray.put(view, listener);
return this;
}
//配置一些万能的参数

/**
* 全屏
*
* @return
*/
public Builder fullWith() {
P.mWith = ViewGroup.LayoutParams.MATCH_PARENT;
return this;
}

/**
* 从底部弹出是否有动画
*
* @param isAnimation
* @return
*/
public Builder formBottom(boolean isAnimation) {
if (isAnimation) {
P.mAnimation = R.style.dialog_from_bottom_anim;
}
P.mGravity = Gravity.BOTTOM;
return this;
}

/**
* 设置宽高
*
* @param with
* @param height
* @return
*/
public Builder setWithAndHeight(int with, int height) {
P.mWith = with;
P.mHeight = height;
return this;
}

/**
* 添加默认动画
*
* @return
*/
public Builder addDefaultAinmation() {
P.mAnimation = R.style.dialog_scale_anim;
return this;
}

/**
* 添加动画
*
* @return
*/
public Builder setAinmation(int styleAnimation) {
P.mAnimation = styleAnimation;
return this;
}

public Builder setOnCancelListener(OnCancelListener onCancelListener) {
P.mOnCancelListener = onCancelListener;
return this;
}

public Builder setOnDismissListener(OnDismissListener onDismissListener) {
P.mOnDismissListener = onDismissListener;
return this;
}

public Builder setOnKeyListener(OnKeyListener onKeyListener) {
P.mOnKeyListener = onKeyListener;
return this;
}

public Builder setCancelable(boolean cancelable) {
P.mCancelable = cancelable;
return this;
}

public AlertDialog show() {
final AlertDialog dialog = create();
dialog.show();
return dialog;
}
}
}
AlertController类是万能dialog效果实现的一个控制类,AlertController类中有提供了一个AlertParams内部类,在AlertParams内部类的apply方法中进行dialog参数的绑定和设置;
package com.dialogdemo.dialog;

import android.content.Context;
import android.content.DialogInterface;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;

/**
* Created by Administrator on 2017/5/21.
*/

class AlertController {
private AlertDialog mAlertDialog;
private Window mWindow;
private DialogViewHelper mViewHelper;

/**
* 获取AlertDialog
*
* @return
*/
public AlertDialog getDialog() {
return mAlertDialog;
}

/**
* 获取AlertDialog的Window
*
* @return
*/
public Window getWindow() {
return mWindow;
}

public AlertController(AlertDialog alertDialog, Window window) {
this.mAlertDialog = alertDialog;
this.mWindow = window;
}

public void setViewHelper(DialogViewHelper mViewHelper) {
this.mViewHelper = mViewHelper;
}

/**
* 设置文本
*
* @param viewid
* @param text
*/
public void setText(int viewid, CharSequence text) {
mViewHelper.setText(viewid, text);
}

public <T extends View> T getView(int viewid) {
return mViewHelper.getView(viewid);
}

/**
* 设置点击
*
* @param viewid
* @param listener
*/
public void setOnClickListener(int viewid, View.OnClickListener listener) {
mViewHelper.setOnClickListener(viewid, listener);
}

public static class AlertParams {
public Context mContext;
public int mThemeResId;
public boolean mCancelable = true;//点击空白是否可以取消
public DialogInterface.OnCancelListener mOnCancelListener;//AlertDialog取消监听
public DialogInterface.OnDismissListener mOnDismissListener;//AlertDialog消失监听
public DialogInterface.OnKeyListener mOnKeyListener;//AlertDialog消失监听按键监听
public View mView;//显示的布局
public int mViewLayoutResId;//布局id
//there can be gaps in the indices.  It is intended to be more memory efficient
//* than using a HashMap to map Integers to Objects, both because it avoids
//存放字体的修改
public SparseArray<CharSequence> mTextArray = new SparseArray<CharSequence>();
//存放点击事件
public SparseArray<View.OnClickListener> mClickArray = new SparseArray<View.OnClickListener>();
//默认宽度
public int mWith = ViewGroup.LayoutParams.WRAP_CONTENT;
//动画
public int mAnimation = 0;
//位置默认居中
public int mGravity = Gravity.CENTER;
//默认高度
public int mHeight = ViewGroup.LayoutParams.WRAP_CONTENT;

public AlertParams(Context context, int themeResId) {
this.mContext = context;
this.mThemeResId = themeResId;
}

/**
* 绑定和设置参数
*
* @param mAlert
*/
public void apply(AlertController mAlert) {
//设置参数
//1设置布局
DialogViewHelper viewHelper = null;
if (mViewLayoutResId != 0) {
viewHelper = new DialogViewHelper(mContext, mViewLayoutResId);
}
if (mView != null) {
viewHelper = new DialogViewHelper();
viewHelper.setContentView(mView);
}
if (viewHelper == null) {
throw new IllegalArgumentException("viewHelper is null");
}
//给dialog设置布局
mAlert.getDialog().setContentView(viewHelper.getContentView());

//设置AlertController辅助类
mAlert.setViewHelper(viewHelper);

//2设置文本
int mTextSize = mTextArray.size();
for (int i = 0; i < mTextSize; i++) {
mAlert.setText(mTextArray.keyAt(i), mTextArray.valueAt(i));
}
//3设置点击
int mClickSize = mClickArray.size();
for (int i = 0; i < mClickSize; i++) {
mAlert.setOnClickListener(mClickArray.keyAt(i), mClickArray.valueAt(i));
}

//4设置自定效果  全屏   从底部弹出   默认动画
Window window = mAlert.getWindow();
//设置位置
window.setGravity(mGravity);
//设置动画
if (mAnimation != 0) {
window.setWindowAnimations(mAnimation);
}
//设置宽高
WindowManager.LayoutParams attributes = window.getAttributes();
attributes.width = mWith;
attributes.height = mHeight;
window.setAttributes(attributes);

}
}
}
最后剩下DialogViewHelper类,这个类比较简单,就是一个辅助类,用于布局的实例化加载,布局中view的缓存及设置一些点击事件等;package com.dialogdemo.dialog;

import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import java.lang.ref.WeakReference;

/**
* Created by Administrator on 2017/5/21.
* AlertDialog View 的辅助处理类
*/

class DialogViewHelper {
private View mContentView = null;
//用于缓存布局中的view
private SparseArray<WeakReference<View>> mViews;

public DialogViewHelper(Context mContext, int mViewLayoutResId) {
this();
//实例化解析加载布局文件
mContentView = LayoutInflater.from(mContext).inflate(mViewLayoutResId, null);
}

public DialogViewHelper() {
mViews = new SparseArray<>();
}

/**
* 设置布局
*
* @param contentView
*/
public void setContentView(View contentView) {
this.mContentView = contentView;
}

/**
* 设置文本
*
* @param viewid
* @param text
*/
public void setText(int viewid, CharSequence text) {
TextView tv = getView(viewid);
if (tv != null) {
tv.setText("" + text);
}
}

public <T extends View> T getView(int viewid) {
WeakReference<View> viewWeakReference = mViews.get(viewid);
View view = null;
if (viewWeakReference != null) {
view = viewWeakReference.get();
}
if (view == null) {
view = mContentView.findViewById(viewid);
if (view != null) {
mViews.put(viewid, new WeakReference<View>(view));
}
}
return (T) view;
}

/**
* 设置点击
*
* @param viewid
* @param listener
*/
public void setOnClickListener(int viewid, View.OnClickListener listener) {
View view = getView(viewid);
if (view != null) {
view.setOnClickListener(listener);
}
}

/**
* 获取contentView
*
* @return
*/
public View getContentView() {
return mContentView;
}
}接下来说下简单的调用:private void thridView() {
List<String> list = new ArrayList();
for (int i = 0; i < 5; i++) {
list.add("item" + i);
}
AlertDialog dialog = new AlertDialog.Builder(this)
.setContentView(R.layout.thrid_layout)
.setCancelable(true)
.show();
RecyclerView recyclerView = dialog.getView(R.id.recycler_view);
//设置布局管理器
recyclerView.setLayoutManager(new LinearLayoutManager(this));
DialogListAdapter adapter = new DialogListAdapter(list, this);
recyclerView.setAdapter(adapter);
}这样就实现了dialog列表的效果,是不是感觉调用很简单。源码地址:https://pan.baidu.com/s/1MuJcrcBYLox4dFud_tJ9kg
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息