萬(wàn)能的dialog封裝

采用Builder設(shè)計(jì)模式,打造一個(gè)萬(wàn)能的dialog襟士,使用時(shí)一句話調(diào)用不用再寫一大串代碼

框架圖.png

一盗飒、搭建框架

創(chuàng)建五個(gè)對(duì)象類

1.AlertDialog ---- Builder創(chuàng)建
public class AlertDialog extends Dialog {
public AlertDialog(Context context, int themeResId) {
    super(context, themeResId);
}
public static class Builder{
}
}
2.AlertController ----AlertParams創(chuàng)建
 class AlertController {
  public AlertController(AlertDialog alertDialog, Window window) {
 }
 public static class AlertParams{
}  
}
3.DialogViewHelper 創(chuàng)建
 public class DialogViewHelper {
public DialogViewHelper(Context context, int layoutResId) {
  }
}
4.AlertDialog -----Builder

AlertDialog 構(gòu)造:

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

Builder 構(gòu)造:

    private final AlertController.AlertParams P;
     /**
     * Creates a builder for an alert dialog that uses the default alert
     * dialog theme.
     * <p>
     * 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.
     * <p>
     * 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.
     * <p>
     * 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.
     * <p>
     * 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);
    }

Builder的其他方法仿Dialog源碼

    /**
     * Creates an {@link AlertDialog} with the arguments supplied to this
     * builder.
     * <p>
     * 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.
     * <p>
     * Calling this method is functionally identical to:
     * <pre>
     *     AlertDialog dialog = builder.create();
     *     dialog.show();
     * </pre>
     */
    public AlertDialog show() {
        final AlertDialog dialog = create();
        dialog.show();
        return dialog;
    }
    /**
     * 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.
     *
     * <p>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}.</p>
     * @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;
    }

自定義一些方法:

     /**
     *設(shè)置布局內(nèi)容的layoutId
     * @param layoutId
     * @return
     */
    public Builder setContentView(int layoutId) {
        P.mView = null;
        P.mViewLayoutResId = layoutId;
        return this;
    }

     /**
     * 設(shè)置文本
     * @param viewId
     * @param text
     * @return
     */
      public Builder setText(int viewId,CharSequence text){
         P.textArray.put(viewId,text);
        return this;

      }
/**
     * 設(shè)置點(diǎn)擊事件
     * @param view
     * @param listener
     * @return
     */
    public Builder setOnClickListener(int view,View.OnClickListener listener){
        P.mClickArray.put(view,listener);
        return this;
    }

    /**
     * 設(shè)置全屏
      * @return
     */
    public Builder fullWidth(){
        P.mWidth= ViewGroup.LayoutParams.MATCH_PARENT;
        return this;

    }


    /**
     * 設(shè)置底部彈出
     * @return
     */
    public Builder fromBottom(boolean isAnimation){
        if (isAnimation){
           P.mAnimation=R.style.dialog_from_bottom_anim;
        }
        P.mGravity= Gravity.BOTTOM;
        return this;

    }

    /**
     * 設(shè)置寬 高
     * @return
     */
    public Builder setWidthAndHeight(int width,int height){
        P.mWidth=width;
        P.mHeight=height;
        return this;

    }

    /**
     * 設(shè)置默認(rèn) 動(dòng)畫
     * @return
     */
    public Builder addDefaultAnimation(){
        P.mAnimation=R.style.dialog_scale_anim;
        return this;
    }

    /**
     * 設(shè)置動(dòng)畫
     * @param styleAnimation
     * @return
     */
    public Builder setAnimation(int styleAnimation){
        P.mAnimation=styleAnimation;
        return this;
    }

基本實(shí)現(xiàn)這些方法

5.AlertController ----AlertParams

AlertController 構(gòu)建;

  private AlertDialog mDialog;
  private Window mWindow;
   private DialogViewHelper mViewHelper;
  public AlertController(AlertDialog alertDialog, Window window) {
       this.mDialog=alertDialog;
       this.mWindow=window;
 }
 public void setViewHelper(DialogViewHelper viewHelper){
    this.mViewHelper=viewHelper;
 }
/**
 * 獲取Dialog
 * @return
 */
public AlertDialog getmDialog() {
    return mDialog;
}


/**
 * 設(shè)置文本
 * @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);
}

/**
 * 設(shè)置點(diǎn)擊事件
 * @param viewId
 * @param listener
 */
public void setOnclickListener(int viewId, View.OnClickListener listener) {
    mViewHelper.setOnclickListener(viewId,listener);
}



/**
 * 獲取Dialog的Window
 * @return
 */
public Window getmWindow() {
    return mWindow;
}

AlertParams 構(gòu)建:

     public Context mContext;
     public int mThemeResId;
    //點(diǎn)擊空白是否能夠取消
    public boolean mCancelable=true;
    //dialog cancel監(jiān)聽
    public DialogInterface.OnCancelListener mOnCancelListener;
    //dialog Dismiss監(jiān)聽
    public DialogInterface.OnDismissListener mOnDismissListener;
    //dialog Key監(jiān)聽
    public DialogInterface.OnKeyListener mOnKeyListener;
    //布局View
    public View mView;
    //布局LayoutId
    public int mViewLayoutResId;
    //存放字體的修改
    public SparseArray<CharSequence> textArray=new SparseArray<>();
    //存放點(diǎn)擊事件
    public SparseArray<View.OnClickListener> mClickArray=new SparseArray<>();
    public int mWidth= ViewGroup.LayoutParams.WRAP_CONTENT;
    //動(dòng)畫
    public int mAnimation=0;
    //位置
    public int mGravity= Gravity.BOTTOM;
    //設(shè)置高度
    public int mHeight=ViewGroup.LayoutParams.WRAP_CONTENT;

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

    }

    /**
     *綁定和設(shè)置參數(shù)
     * @param mAlert
     */
    public void apply(AlertController mAlert) {

        //1.設(shè)置布局
        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("請(qǐng)?jiān)O(shè)置布局setContentView");
        }
        //給Dialog設(shè)置布局
       mAlert.getmDialog().setContentView(viewHelper.getContentView());

        mAlert.setViewHelper(viewHelper);
        //2.設(shè)置文本
        int textArraySize = textArray.size();
        for (int i = 0; i <textArraySize; i++) {
            mAlert.setText(textArray.keyAt(i),textArray.valueAt(i));
        }

        //3.設(shè)置點(diǎn)擊
        int clickArraySize = mClickArray.size();
        for (int i = 0; i <clickArraySize; i++) {
            mAlert.setOnclickListener(mClickArray.keyAt(i), mClickArray.valueAt(i));
        }



        //4.配置自定義的效果 全屏 從底部彈出 默認(rèn)動(dòng)畫
        Window window=mAlert.getmWindow();
        //設(shè)置動(dòng)畫
        window.setGravity(mGravity);

        if (mAnimation!=0){
            window.setWindowAnimations(mAnimation);
        }

        //設(shè)置寬高
        WindowManager.LayoutParams params = window.getAttributes();
        params.width=mWidth;
        params.height=mHeight;
        window.setAttributes(params);
    }

DialogViewHelper 輔助類:

 private View mContentView=null;
 private SparseArray<WeakReference<View>> mView;
  public DialogViewHelper(Context context, int layoutResId) {
    this();
    mContentView= LayoutInflater.from(context).inflate(layoutResId,null);
   }
  public DialogViewHelper() {
    mView=new SparseArray<>();
   }
/**
 * 設(shè)置布局
 * @param contentView
 */
public void setContentView(View contentView) {
    this.mContentView = contentView;
}

/**
 * 設(shè)置文本
 * @param viewId
 * @param text
 */
public void setText(int viewId, CharSequence text) {
    //每次都findViewById 減少findViewById的次數(shù)
    TextView tv=getView(viewId);
  //        TextView tv= (TextView) mContentView.findViewById(viewId);
    if (tv!=null){
        tv.setText(text);
    }
}

public  <T extends View> T getView(int viewId) {

    WeakReference<View> viewWeakReference = mView.get(viewId);
    View view=null;
    if (viewWeakReference!=null){
        view= viewWeakReference.get();
    }
    if (view==null){
        view=  mContentView.findViewById(viewId);
        if (view!=null){
            mView.put(viewId,new WeakReference<>(view));
        }

    }
    return (T) view;
}

/**
 * 設(shè)置點(diǎn)擊事件
 * @param viewId
 * @param listener
 */
public void setOnclickListener(int viewId, View.OnClickListener listener) {
    View view=getView(viewId);
    if (view!=null){
        view.setOnClickListener(listener);
    }
}

/**
 * 獲取mContentView
 * @return
 */
public View getContentView() {
    return mContentView;
}

二嚷量、使用

            AlertDialog dialog= new AlertDialog.Builder(MainActivity.this)
                    .setContentView(R.layout.detail_comment_dialog)
                    .setText(R.id.submit_btn, "發(fā)送")
                    .fullWidth().show();

             final EditText editText = dialog.getView(R.id.comment_editor);

             dialog.setOnclickListener(R.id.submit_btn, new               View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(MainActivity.this,editText.getText().toString(),Toast.LENGTH_SHORT).show();
                }
            });

三、擴(kuò)展

寬展只需要在Builder中寫相應(yīng)方法逆趣,AlertParams中設(shè)置就ok

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蝶溶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宣渗,更是在濱河造成了極大的恐慌抖所,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痕囱,死亡現(xiàn)場(chǎng)離奇詭異田轧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鞍恢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門傻粘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人帮掉,你說(shuō)我怎么就攤上這事弦悉。” “怎么了蟆炊?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵稽莉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我涩搓,道長(zhǎng)污秆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任昧甘,我火速辦了婚禮良拼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疾层。我一直安慰自己将饺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布痛黎。 她就那樣靜靜地躺著予弧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪湖饱。 梳的紋絲不亂的頭發(fā)上掖蛤,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音井厌,去河邊找鬼蚓庭。 笑死致讥,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的器赞。 我是一名探鬼主播垢袱,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼港柜!你這毒婦竟也來(lái)了请契?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤夏醉,失蹤者是張志新(化名)和其女友劉穎爽锥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體畔柔,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡氯夷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了靶擦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腮考。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖奢啥,靈堂內(nèi)的尸體忽然破棺而出秸仙,到底是詐尸還是另有隱情,我是刑警寧澤桩盲,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布寂纪,位于F島的核電站,受9級(jí)特大地震影響赌结,放射性物質(zhì)發(fā)生泄漏捞蛋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一柬姚、第九天 我趴在偏房一處隱蔽的房頂上張望拟杉。 院中可真熱鬧,春花似錦量承、人聲如沸搬设。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拿穴。三九已至,卻和暖如春忧风,著一層夾襖步出監(jiān)牢的瞬間默色,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工狮腿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腿宰,地道東北人呕诉。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吃度,于是被迫代替她去往敵國(guó)和親甩挫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容