Builder設計模式構建萬能Dialog
阿新 • • 發佈:2019-01-10
首先看下AlertDialog解析圖
首先要會用AlertDialog的使用
new AlertDialog.Builder(this) .setIcon(R.mipmap.ic_launcher) .setTitle("訊息") .setPositiveButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }) .setNegativeButton("取消"對原始碼解析我們可以得到上圖的結果,接下來就是自定義一個Dialog,因為我在我的程式碼中寫了很多註解我就不解釋了, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }) .create().show();
第一步自定義一個AlertDialog
public class AlertDialog extends Dialog { AlertController mAlert第二步:自定義一個AlertContorller; public AlertDialog(@NonNull Context context, @StyleRes int themeResId) { super(context, themeResId); mAlert = new AlertController(this, getWindow()); } public void setText(int viewId, CharSequence text) { mAlert.setText(viewId, text); } public void setOnClickListener(int viewId, View.OnClickListener listener) { mAlert.setOnClickListener(viewId, listener); } /** * 減少findviewById的次數 */ public <T extends View> T getView(int viewId) { return mAlert.getView(viewId); } public static class Builder { private final AlertController.AlertParams P; public Builder(@NonNull Context context) { this(context, R.style.dialog); } public Builder(@NonNull Context context, @StyleRes int themeResId) { P = new AlertController.AlertParams(context, themeResId); } public AlertDialog create() { final AlertDialog dialog = new AlertDialog(P.mContext, P.themeResId); 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; } /** * 設定View */ public AlertDialog.Builder setContentView(int layoutResId) { P.mView = null; P.mViewLayoutResId = layoutResId; return this; } public AlertDialog.Builder setContentView(View view) { P.mView = view; P.mViewLayoutResId = 0; return this; } /** * 存放自定義View中的文字 */ public AlertDialog.Builder setText(int layoutId, CharSequence text) { P.mTextArray.put(layoutId, text); return this; } /** * 存放自定義View中按鈕點選事件 */ public AlertDialog.Builder setOnClickListener(int layoutId, View.OnClickListener listener) { P.mClickArray.put(layoutId, listener); return this; } //配置一些萬能引數 public AlertDialog.Builder fullWidth() { P.mWidth = ViewGroup.LayoutParams.MATCH_PARENT; return this; } //設定動畫 public AlertDialog.Builder fromButtom(boolean isAnimation) { if (isAnimation) { P.mAnimation = R.style.dialog_from_bottom_anim; } P.mGravity = Gravity.BOTTOM; return this; } public AlertDialog.Builder setWidthAndHeight(int width, int heigth) { P.mWidth = width; P.mHeigth = heigth; return this; } //設定預設動畫 public AlertDialog.Builder AddDefaultAnimation() { P.mAnimation = R.style.dialog_scale_animation; return this; } //設定動畫 public AlertDialog.Builder setAnimation(int styleAnimation) { P.mAnimation = styleAnimation; return this; } public AlertDialog show() { final AlertDialog dialog = create(); dialog.show(); return dialog; } } }
class AlertController { private Window mWindow; private AlertDialog mAlertDialog; private ViewHelper mViewHelper; public AlertController(AlertDialog alertDialog, Window window) { this.mWindow = window; this.mAlertDialog = alertDialog; } public void setViewHelper(ViewHelper mViewHelper) { this.mViewHelper = mViewHelper; } public Window getWindow() { return mWindow; } public AlertDialog getDialog() { return mAlertDialog; } public void setText(int viewId, CharSequence text) { mViewHelper.setText(viewId,text); } public void setOnClickListener(int viewId, View.OnClickListener listener) { mViewHelper.setOnClickListener(viewId,listener); } /** * 減少findviewById的次數 */ public <T extends View> T getView(int viewId) { return mViewHelper.getView(viewId); } public static class AlertParams { public Context mContext; public int themeResId; public boolean mCancelable = true;//點選空白是否能夠取消 public DialogInterface.OnCancelListener mOnCancelListener;//dialog Cancel監聽 public DialogInterface.OnDismissListener mOnDismissListener;//dialog Dismiss監聽 public DialogInterface.OnKeyListener mOnKeyListener;//按鍵監聽 //View載入佈局 public View mView; //id載入佈局 public int mViewLayoutResId; //存放自定義view中的文字 SparseArray<CharSequence> mTextArray = new SparseArray<>(); //存放自定義view中的點選事件 SparseArray<View.OnClickListener> mClickArray = new SparseArray<>(); public int mWidth = ViewGroup.LayoutParams.WRAP_CONTENT; public int mGravity = Gravity.CENTER; public int mAnimation; public int mHeigth = ViewGroup.LayoutParams.WRAP_CONTENT; public AlertParams(Context context, int themeResId) { this.mContext = context; this.themeResId = themeResId; } /** * 繫結和設定引數 * * @param mAlert */ public void apply(AlertController mAlert) { //設定引數 //1.設定佈局 ViewHelper viewHelper = null; if (mViewLayoutResId != 0) { viewHelper = new ViewHelper(mContext, mViewLayoutResId); } if (mView != null) { viewHelper = new ViewHelper(); viewHelper.setContentView(mView); } if (viewHelper == null) { throw new IllegalArgumentException("請設定佈局setContentView()"); } //給dialog設定佈局 mAlert.getDialog().setContentView(viewHelper.getContentView()); //2.設定文字 int textArraysize = mTextArray.size(); for (int i = 0; i < textArraysize; i++) { viewHelper.setText(mTextArray.keyAt(i), mTextArray.valueAt(i)); } //3.設定點選事件 int clickSize = mClickArray.size(); for (int i = 0; i < clickSize; i++) { viewHelper.setOnClickListener(mClickArray.keyAt(i), mClickArray.valueAt(i)); } mAlert.setViewHelper(viewHelper); //4.配置自定義效果 全屏 從底部彈出 預設動畫 Window window = mAlert.getWindow(); //設定位置 window.setGravity(mGravity); //設定動畫 if (mAnimation != 0) { window.setWindowAnimations(mAnimation); } //設定寬和高 WindowManager.LayoutParams params = window.getAttributes(); params.width = mWidth; params.height = mHeigth; window.setAttributes(params); } } }第三步:自定義一個ViewHelper
public class ViewHelper { private View mContentView;//佈局View //減少findviewById private SparseArray<WeakReference<View>> mViews; public ViewHelper(Context context, int viewLayoutResId) { this();//此方法不可少,呼叫的是無參ViewHelper mContentView = LayoutInflater.from(context).inflate(viewLayoutResId, null); } public ViewHelper() { mViews = new SparseArray<>(); } public void setContentView(View contentView) { this.mContentView = contentView; } public void setText(int viewId, CharSequence text) { TextView tv = getView(viewId); if (tv != null) { tv.setText(text); } } public void setOnClickListener(int viewId, View.OnClickListener listener) { View view = getView(viewId); if(view!=null){ view.setOnClickListener(listener); } } public View getContentView() { return mContentView; } /** * 減少findviewById的次數 */ public <T extends View> T getView(int viewId) { WeakReference<View> weakReference = mViews.get(viewId); View view = null; if(weakReference!=null){ view=weakReference.get(); } if (view == null) { view = mContentView.findViewById(viewId); if (view != null) { mViews.put(viewId, new WeakReference<>(view)); } } return (T) view; } }最後這裡寫下我自己使用的樣式和佈局
①dialog的樣式
<style name="dialog" parent="@android:style/Theme.Dialog"> <!--沒有邊框--> <item name="android:windowFrame">@null</item> <!--是否懸浮在activity之上--> <item name="android:windowIsFloating">true</item> <!--沒有標題--> <item name="android:windowIsTranslucent">true</item> <!--背景透明--> <item name="android:background">@android:color/transparent</item> <!--模糊--> <item name="android:backgroundDimEnabled">true</item> <!--沒有標題--> <item name="android:windowNoTitle">true</item> </style>②進入時的動畫
<style name="dialog_from_bottom_anim"> <item name="android:windowEnterAnimation">@anim/dialog_from_bottom_anim_in</item> <item name="android:windowExitAnimation">@anim/dialog_from_bottom_anim_out</item> </style>
③預設縮放動畫
<style name="dialog_scale_anim"> <item name="android:windowEnterAnimation">@anim/dialog_scale_anim_in</item> <item name="android:windowExitAnimation">@anim/dialog_scale_anim_out</item> </style>
dialog_from_bottom_anim_in:
<set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="400" android:fromXDelta="0" android:fromYDelta="1000" android:toYDelta="0" android:toXDelta="0" /> </set>dialog_from_bottom_anim_out:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="400" android:fromXDelta="0" android:fromYDelta="0" android:toYDelta="1000"/> </set>
dialog_scale_anim_in:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <scale android:duration="135" android:fromXScale="0.8" android:fromYScale="0.8" android:pivotX="50%" android:pivotY="50%" android:toXScale="1.05" android:toYScale="1.05" /> <scale android:duration="105" android:fromXScale="1.05" android:fromYScale="1.05" android:pivotX="50%" android:pivotY="50%" android:startOffset="135" android:toXScale="0.95" android:toYScale="0.95" /> <scale android:duration="60" android:fromXScale="0.95" android:fromYScale="0.95" android:pivotX="50%" android:pivotY="50%" android:startOffset="240" android:toXScale="1.0" android:toYScale="1.0" /> <alpha android:duration="90" android:fromAlpha="0.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="1.0" /> </set>dialog_scale_anim_out:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <scale android:duration="150" android:fromXScale="1.0" android:fromYScale="1.0" android:pivotX="50%" android:pivotY="50%" android:toXScale="0.6" android:toYScale="0.6" /> <alpha android:duration="150" android:fromAlpha="1.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="0.0" /> </set>
dialog_test:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root_view" android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/comment_dialog_bg" android:orientation="vertical" android:padding="10.0dip"> <EditText android:id="@+id/comment_editor" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/bg_detail_comment_editor" android:hint="@string/ss_share_hint" android:maxHeight="120.0dip" android:padding="9.0dip" android:textColor="@color/comment_dialog_content_text" android:textSize="16.0sp" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10.0dip" android:gravity="center_vertical"> <TextView android:id="@+id/share_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginRight="10.0dip" android:text="@string/comment_dialog_share_label" android:textColor="@color/comment_dialog_share_text" android:textSize="13.0sp" /> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"> <ImageView android:id="@+id/account_icon_weibo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/account_icon_weibo" /> <ImageView android:id="@+id/account_icon_tencent" android:layout_width="wrap_content" android:layout_marginLeft="10dp" android:layout_height="wrap_content" android:src="@drawable/account_icon_tencent" /> </LinearLayout> <LinearLayout android:id="@+id/platform_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/share_label" android:orientation="horizontal" /> <TextView android:id="@+id/submit_btn" android:layout_width="50.0dip" android:layout_height="25.0dip" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:background="@drawable/bg_comment_submit" android:gravity="center" android:text="@string/comment_dialog_send" android:textColor="@color/comment_dialog_submit_text" android:textSize="13.0sp" /> <TextView android:id="@+id/text_limit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginRight="10.0dip" android:layout_toLeftOf="@id/submit_btn" android:textSize="13.0sp" android:visibility="invisible" /> </LinearLayout> </LinearLayout> </FrameLayout>
使用很簡單:
findViewById(R.id.ceshi).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AlertDialog dialog = new AlertDialog.Builder(MainActivity.this) .setContentView(R.layout.dialog_test) .fullWidth() .fromButtom(true) .show(); dialog.setOnClickListener(R.id.send, new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "點選了傳送", Toast.LENGTH_SHORT).show(); } }); } });
效果圖如下: