打造屬于自己的Dialog---仿安卓系統自帶原生Dialog設計

前言:這個過程中遇到了兩個問題,都比較基礎,第一個問題是:系統無法識別圖片資源,不過還好,被我刪了之后就很好的運行了,第二個也是比較鬼畜的問題,錯把==符號變成了!=結果導致閃退缺不報錯!現在我們為什么要來這一個屬于自己的dialog,原因很簡單,安卓自帶的太丑了!!!而且局限性強,那么為了解決這個問題,分開view與邏輯,更方便的進行拓展下面我們需要用一個非常常見的設計模式builder!


buidler設計模式:一個比方——組裝電腦,一系列產品的電腦,可以有不同的配置,不同的cpu,不同的arm,一個電腦最后的模樣是取決于各個配件的組合,同樣的道理,我們在使用dialog的過程中也會有這樣那樣的需求,因此,1.為了更靈活的去運用dialog,實現更多樣化。2.為了易拓展,view與實現邏輯分開!等…


具體需要的類有三個,DialogViewhelper(輔助類存在),AlertDialog,AerltController



下面簡單來介紹一下這三個類吧,先從AlertDialog介紹起,為什么從這個介紹起呢,因為如果你來寫,也會從這里寫起,主要思路是先用AlertDialog來講我們所所需要的,參數傳遞進來,當然它也是這個的入口,然后是AlertController這個用來傳遞參數,到最后,用DialogViewhelper進行最終的實現,當然如果你不想寫那個輔助類也行下面簡單來介紹一下這三個類吧,先從AlertDialog介紹起,為什么從這個介紹起呢,因為如果你來寫,也會從這里寫起,主要思路是先用AlertDialog來講我們所所需要的,參數傳遞進來,當然它也是這個的入口,然后是AlertController這個用來傳遞參數,到最后,用DialogViewhelper進行最終的實現,當然如果你不想寫那個輔助類也行



1,AerltDialog類:繼承了Dialog(值得注意的是這里繼承的只是Dialog而非AlertDialog),這里具體的一些思路是,構造函數出來,然后new一個AlertController出來然后,設置一些傳遞參數用的方法如:setText和getview這些,當然主要的還是builder里面的內容是直接仿安卓源碼的,將數據放入P中,然后進行傳遞!當然這里最好加上一個通過id去尋找的setContextView,同時值得注意的是,無論是文本還是事件不止只有一個,所以用SparseArray儲存起來!為什么要使用這個呢,很簡單在安卓源碼里頭,有一句英語表明了如果是鍵值對為int加值的這種,這個比hasmp更優越!

這里有想法的人最好去看看源碼!!

package com.example.baselibrary.baseActvity.dialog;

import android.app.Dialog;

import android.content.Context;

import android.view.Gravity;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ListView;

import com.example.baselibrary.R;

/**

* Created by 廖成康 on 2017/4/26.

*/

public class AlertDialog extends Dialog

{

?private AlertController mAlert;

?public AlertDialog(Context context, int themeResId)

?{

? ?super(context, themeResId);

? ?mAlert= new AlertController(this,getWindow());

?}

?/**

? * 設置文本

? * @param ResId

? * @param text

? */

?public void setText(int ResId,CharSequence text)

?{

? ?mAlert.setText(ResId,text);

?}

?/**

? * 設置getView方法

? * @param ResId

? * @param

* @return

*/

?public T getView(int ResId)

?{

? ?return mAlert.getView(ResId);

?}

?/**

? * 設置點擊事件

? *

? * @param ResId

? * @param listener

? */

?public void ?setOnClickLisnter(int ResId,View.OnClickListener listener)

?{

? ?mAlert.setOnClickLisnter(ResId,listener);

?}

?public static class Builder

?{

? ?public final AlertController.AlertParams P;

? ?/**

? ? * Creates a builder for an alert dialog that uses the default alert

? ? * dialog theme.

? ? *

* The default alert dialog theme is defined by

* {@link android.R.attr#alertDialogTheme} within the parent

* {@code context}'s theme.

*

* @param context the parent context

*/

public Builder(Context context)

{

this(context, R.style.dialog);

}

? ?/**

? ? * Creates a builder for an alert dialog that uses an explicit theme

? ? * resource.

? ? *

* The specified theme resource ({@code themeResId}) is applied on top

* of the parent {@code context}'s theme. It may be specified as a

* style resource containing a fully-populated theme, such as

* {@link android.R.style#Theme_Material_Dialog}, to replace all

* attributes in the parent {@code context}'s theme including primary

* and accent colors.

? ? *

* To preserve attributes such as primary and accent colors, the

* {@code themeResId} may instead be specified as an overlay theme such

* as {@link android.R.style#ThemeOverlay_Material_Dialog}. This will

* override only the window attributes necessary to style the alert

* window as a dialog.

? ? *

* Alternatively, the {@code themeResId} may be specified as {@code 0}

* to use the parent {@code context}'s resolved value for

* {@link android.R.attr#alertDialogTheme}.

*

* @param context ?the parent context

* @param themeResId the resource ID of the theme against which to inflate

* ? ? ? ? ?this dialog, or {@code 0} to use the parent

* ? ? ? ? ?{@code context}'s default alert dialog theme

*/

public Builder(Context context, int themeResId)

{

P =new AlertController.AlertParams(context,themeResId);

}

? ?/**

? ? * Sets a custom view to be the contents of the alert dialog.

? ? *

* When using a pre-Holo theme, if the supplied view is an instance of

* a {@link ListView} then the light background will be used.

? ? *

* Note:<4> To ensure consistent styling, the custom view

* should be inflated or constructed using the alert dialog's themed

* context obtained via {@link #getContext()}.

*

* @param view the view to use as the contents of the alert dialog

* @return this Builder object to allow for chaining of calls to set

* methods

*/

public Builder setContextView(View view) {

P.mView = view;

P.mViewLayoutResId = 0;

return this;

}

? ?/**

? ? * 設置布局Id

? ? * @param ResId

? ? * @return

? ? */

? ?public Builder setContextView(int ResId){

? ? ?P.mView=null;

? ? ?P.mViewLayoutResId=ResId;

? ? ?return this;

? ?}

/**

* 設置文本

* @param ResId

* @param text

* @return

*/

? ?public Builder setText( int ResId,CharSequence text)

? ?{

? ? ?P.mTextArray.put(ResId,text);

? ? ?return this;

? ?}

? ?/**

? ? * 設置點擊事件

? ? * @param view

? ? * @param listener

? ? * @return

? ? */

? ?public Builder setOnClickLisnter(int view,View.OnClickListener listener)

? ?{

? ? ?P.mClickArray.put(view,listener);

? ? ?return this;

? ?}

? ?/**

? ? * 設置寬度

? ? * @return

? ? */

? ?public Builder fullWidth()

? ?{

? ? ?P.mWidth= ViewGroup.LayoutParams.MATCH_PARENT;

? ? ?return this;

? ?}

? ?public Builder fromButton(boolean isAnimation)

? ?{

? ? ?if (isAnimation)

? ? ?{

? ? ? ?P.mAnimations=R.style.dialog_from_bottom_anim;

? ? ?}

? ? ?P.mGrivity= Gravity.BOTTOM;

? ? ?return this;

? ?}

? ?/**

? ? * 設置Dialog的寬高

? ? * @param width

? ? * @param height

? ? * @return

? ? */

? ?public Builder setWidthAndHeight(int width, int height){

? ? ?P.mWidth = width;

? ? ?P.mHeight = height;

? ? ?return this;

? ?}

? ?/**

? ? * 添加默認動畫

? ? * @return

? ? */

? ?public Builder addDefaultAnimation(){

? ? ?P.mAnimations = R.style.dialog_scale_anim;

? ? ?return this;

? ?}

? ?/**

? ? * 設置動畫

? ? * @param styleAnimation

? ? * @return

? ? */

? ?public Builder setAnimations(int styleAnimation){

? ? ?P.mAnimations = styleAnimation;

? ? ?return this;

? ?}

? ?/**

? ? * Sets whether the dialog is cancelable or not. Default is true.

? ? *

? ? * @return This Builder object to allow for chaining of calls to set methods

? ? */

? ?public Builder setCancelable(boolean cancelable) {

? ? ?P.mCancelable = cancelable;

? ? ?return this;

? ?}

? ?/**

? ? * Sets the callback that will be called if the dialog is canceled.

? ? *

? ? *

Even in a cancelable dialog, the dialog may be dismissed for reasons other than

? ? * being canceled or one of the supplied choices being selected.

? ? * If you are interested in listening for all cases where the dialog is dismissed

? ? * and not just when it is canceled, see

? ? * {@link #setOnDismissListener(android.content.DialogInterface.OnDismissListener) setOnDismissListener}.

* @see #setCancelable(boolean)

* @see #setOnDismissListener(android.content.DialogInterface.OnDismissListener)

*

* @return This Builder object to allow for chaining of calls to set methods

*/

public Builder setOnCancelListener(OnCancelListener onCancelListener) {

P.mOnCancelListener = onCancelListener;

return this;

}


?/**

? ? * Sets the callback that will be called when the dialog is dismissed for any reason.

? ? *

? ? * @return This Builder object to allow for chaining of calls to set methods

? ? */

? ?public Builder setOnDismissListener(OnDismissListener onDismissListener) {

? ? ?P.mOnDismissListener = onDismissListener;

? ? ?return this;

? ?}

? ?/**

? ? * Sets the callback that will be called if a key is dispatched to the dialog.

? ? *

? ? * @return This Builder object to allow for chaining of calls to set methods

? ? */

? ?public Builder setOnKeyListener(OnKeyListener onKeyListener) {

? ? ?P.mOnKeyListener = onKeyListener;

? ? ?return this;

? ?}

? ?/**

? ? * Creates an {@link AlertDialog} with the arguments supplied to this

? ? * builder.

? ? *

? ? * Calling this method does not display the dialog. If no additional

? ? * processing is needed, {@link #show()} may be called instead to both

? ? * create and display the dialog.

? ? */

? ?public AlertDialog create() {

? ? ?// Context has already been wrapped with the appropriate theme.

? ? ?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;

? ?}

? ?/**

? ? * Creates an {@link AlertDialog} with the arguments supplied to this

? ? * builder and immediately displays the dialog.

? ? *

* Calling this method is functionally identical to:

? ? *

* ? AlertDialog dialog = builder.create();

* ? dialog.show();

*

*/

public AlertDialog show() {

final AlertDialog dialog = create();

dialog.show();

return dialog;

}

?}

}

2.AlertContorller:

這個類里面我們是給了一系列參數了的,那么這個類是干什么的呢很簡單,傳過來的參數傳到vieqhelper里面進行實現,當然,在這個過程中,我們需要做一些優化,比如說,我們需要做,一些參數在值上默認,容錯等等,這些就不具體將了注視里面相當清楚了,

而我這里主要實現了什么東西呢?1.設置文本,2.設置監聽事件,3.配置全屏 從底部彈出,動畫等!!








package com.example.baselibrary.baseActvity.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 廖成康 on 2017/4/26.

*/

class AlertController

{

?private DialogViewHelper mdialogViewHelper;

?private AlertDialog malertDialog;

?private Window mwindow;

?public AlertController(AlertDialog alertDialog, Window window)

?{

? ? ?this.malertDialog=alertDialog;

? ? ?this.mwindow=window;

?}

?public void setMdialogViewHelper(DialogViewHelper dialogViewHelper)

?{

? ?this.mdialogViewHelper=dialogViewHelper;

?}

?/***

? *

? * 設置文本

? *

? * 具體實現在DialogViewHelper

? *

? * @param resId

? * @param text

? */

?public void setText(int resId, CharSequence text)

?{

? mdialogViewHelper.setText(resId,text);

?}

?/**

? * 設置獲取得到View

? *

? * @param resId

? * @param

* @return

*/

?public T getView(int resId)

?{

? ?return mdialogViewHelper.getView(resId);

?}

?/**

? * 設置點擊事件

? *

? * @param resId

? * @param listener

? */

?public void setOnClickLisnter(int resId, View.OnClickListener listener) {

?mdialogViewHelper.setOnClickLisnter(resId,listener);

?}

?/**

? * 獲取得到dialog

? *

? * @return

? */

?public AlertDialog getMalertDialog()

?{

? ?return malertDialog;

?}

?/**

? * 獲取得到window

? *

? *

? * @return

? */

?public Window getMwindow()

?{

? ?return mwindow;

?}


?/**

? * 一個媒介,從AlertDialog里面得到參數

? *

? */

?public static class AlertParams

?{

? ?public View mView;

? ?//布局的Id

? ?public int mViewLayoutResId;

? ?///上下文

? ?public Context mContext;

? ?///主題的Id

? ?public int mThemeResId;

? ?///點擊空白處是否取消

? ?public boolean mCancelable=true;

? ?///三個參數

? ?public DialogInterface.OnCancelListener mOnCancelListener;

? ?public DialogInterface.OnDismissListener mOnDismissListener;

? ?public DialogInterface.OnKeyListener mOnKeyListener;

? ?// 存放字體的修改

? ?public SparseArray mTextArray = new SparseArray<>();

? ?// 存放點擊事件

? ?public SparseArray mClickArray = new SparseArray<>();

? ?///設置寬度 自定義參數

? ?public int mWidth= ViewGroup.LayoutParams.WRAP_CONTENT;

? ?//設置位置 自定義參數

? ?public int mGrivity= Gravity.CENTER;

? ?//設置高度 自定義參數

? ?public int mHeight=ViewGroup.LayoutParams.WRAP_CONTENT;

? ?//設置動畫

? ?public int mAnimations=0;

? ?public AlertParams(Context context,int mThemeResId)

? ?{

? ? ? ?this.mContext=context;

? ? ? ?this.mThemeResId=mThemeResId;

? ?}

? ?public void apply(AlertController mAlert)

? ?{

? ? ?///完善需要設置一些參數

? ? //1.給DialogViewhelper設置view布局

? ? ?DialogViewHelper viewHelper=null;

? ? ?if (mViewLayoutResId!=0)

? ? ?{

? ? ? ?viewHelper=new DialogViewHelper(mContext,mViewLayoutResId);

? ? ?}

? ? ?//2.設置view

? ? ?if (mView!=null)

? ? ?{

? ? ? ?viewHelper=new DialogViewHelper();

? ? ? ?viewHelper.setContextView(mView);

? ? ?}

? ? ?//容錯處理

? ? ?if (viewHelper==null)

? ? ?{

? ? ? ?throw new IllegalArgumentException("還沒有設置布局");

? ? ?}

? ? ?///繼承的是Dialog

? ? ?mAlert.getMalertDialog().setContentView(viewHelper.getmContextView());

? ? ? ///給輔助類設置viewhelper,對上面傳參數有必要

? ? ?mAlert.setMdialogViewHelper(viewHelper);

? ? ?//2.設置文本

? ? ?int mtextsize=mTextArray.size();

? ? ?for (int length=0;length

? ? ?{

? ? ? mAlert.setText(mTextArray.keyAt(length),mTextArray.valueAt(length));

? ? ?}

? ? ?///設置監聽事件

? ? ?int mclicksize=mClickArray.size();

? ? ?for (int i=0;i

? ? ?{

? ? ? ?mAlert.setOnClickLisnter(mClickArray.keyAt(i),mClickArray.valueAt(i));

? ? ?}

? ? ? ///配置自定義效果 全屏 從底部彈出 動畫

? ? ?Window window=mAlert.getMwindow();

? ? ?window.setGravity(mGrivity);

? ? ?///設置懂動畫

? ? ?if (mAnimations!=0)

? ? ?{

? ? ? ?window.setWindowAnimations(mAnimations);

? ? ?}

? ? ?WindowManager.LayoutParams params=window.getAttributes();

? ? ?params.width=mWidth;

? ? ?params.height=mHeight;

? ? ?window.setAttributes(params);

? ?}

?}

}

3.最后,這個類里面就是我們實現的最后的目的了,這里面有一個叫軟應用的,用來防止一些情況的發生所使用的,值得注意一下


當然這個類并不是說只有它才實現而已,前面的第二個類也已經實現了一些功能,這里的話主要實現的是設置文本和設置點擊事件!這兩


package com.example.baselibrary.baseActvity.dialog;

/**

* Created by 廖成康 on 2017/4/26.

*/

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;

/**

* Dialog 作為View的輔助類

*

*/

class DialogViewHelper

{

?private View mContextView=null;

?//// 防止霸氣側漏

?private SparseArray> mView;

?public DialogViewHelper(Context context,int viewId)

?{

? this();

? mContextView= LayoutInflater.from(context).inflate(viewId,null);

?}

?public DialogViewHelper()

?{

?mView=new SparseArray<>();

?}

?/**

? * 設置布局

? * @param context

? */

?public void setContextView(View context)

?{

? ?this.mContextView=context;

?}

?/**

? * 獲取布局

? *

? */

?public View getmContextView()

?{

? ?return mContextView;

?}

? ?public T getView(int viewId)

? ?{

? ? ?WeakReference viewWeakReference=mView.get(viewId);

? ? ?//側漏問題

? ? ?View view=null;

? ? ?if (viewWeakReference!=null)

? ? ?{

? ? ? ?view=viewWeakReference.get();

? ? ?}

? ? ?if (view==null)

? ? ?{

? ? ? ?view=mContextView.findViewById(viewId);

? ? ? ?if (view==null)

? ? ? ?{

? ? ? ? ?mView.put(viewId,new WeakReference(view));

? ? ? ?}

? ? ?}

? ? ?return (T) view;

? ?}

?/**

? * 設置文本

? * @param resId

? * @param text

? */

?public void setText(int resId,CharSequence text)

?{

? TextView textView=getView(resId);

? if (textView!=null)

? {

? ? textView.setText(text);

? }

?}

?/**

? * 設置點擊事件

? *

? * @param ResId

? * @param listener

? */

?public void setOnClickLisnter(int ResId,View.OnClickListener listener)

?{

? ?View view=getView(ResId);

? ?if (view!=null)

? ?{

? ? ? view.setOnClickListener(listener);

? ?}

?}

}

到這里,資源這些的話,如果想要在聯系我吧1269729771扣扣號!!!!今天要早睡了,寫在簡書強,有些東西可能不太清楚,莫怪了哈!!

圖片發自簡書App

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,185評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,446評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,951評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,189評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,718評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,800評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,420評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,755評論 2 371

推薦閱讀更多精彩內容