這是參照系統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