打造属于自己的Dialog---仿安卓系统自带原生Dialog设计

来源:互联网 发布:java汽车租赁管理系统 编辑:程序博客网 时间:2024/05/21 18:35
前言:这个过程中遇到了两个问题,都比较基础,第一个问题是:系统无法识别图片资源,不过还好,被我删了之后就很好的运行了,第二个也是比较鬼畜的问题,错把==符号变成了!=结果导致闪退缺不报错!现在我们为什么要来这一个属于自己的dialog,原因很简单,安卓自带的太丑了!!!而且局限性强,那么为了解决这个问题,分开view与逻辑,更方便的进行拓展下面我们需要用一个非常常见的设计模式builder!


buidler设计模式:一个比方——组装电脑,一系列产品的电脑,可以有不同的配置,不同的cpu,不同的arm,一个电脑最后的模样是取决于各个配件的组合,同样的道理,我们在使用dialog的过程中也会有这样那样的需求,因此,1.为了更灵活的去运用dialog,实现更多样化。2.为了易拓展,view与实现逻辑分开!等…



具体需要的类有三个,DialogViewhelper(辅助类存在),AlertDialog,AerltController




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 <T>     * @return     */    public <T extends View> 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.         * <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);        }        /**         * Sets a custom view to be the contents of the alert dialog.         * <p/>         * When using a pre-Holo theme, if the supplied view is an instance of         * a {@link ListView} then the light background will be used.         * <p/>         * <strong>Note:</strong> 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.         *         * <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;        }        /**         * 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;        }    }}
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 <T>     * @return     */    public <T extends View> 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<CharSequence> mTextArray = new SparseArray<>();        // 存放点击事件        public SparseArray<View.OnClickListener> 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<mtextsize;length++)            {             mAlert.setText(mTextArray.keyAt(length),mTextArray.valueAt(length));            }            ///设置监听事件            int  mclicksize=mClickArray.size();            for (int i=0;i<mclicksize;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<WeakReference<View>> 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 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=mContextView.findViewById(viewId);               if (view==null)               {                   mView.put(viewId,new WeakReference<View>(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扣扣号!!!!今天要早睡了








1 0
原创粉丝点击