Builder设计模式构建万能Dialog

来源:互联网 发布:企业彩铃录音软件 编辑:程序博客网 时间:2020/10/24 23:04

首先看下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("取消", new DialogInterface.OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {        }    })    .create().show();
对源码解析我们可以得到上图的结果,接下来就是自定义一个Dialog,因为我在我的代码中写了很多注解我就不解释了

第一步自定义一个AlertDialog

public class AlertDialog extends Dialog {    AlertController mAlert;    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;        }    }}
第二步:自定义一个AlertContorller

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>
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_test:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <EditText        android:id="@+id/edit_query"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">        <TextView            android:id="@+id/tv_dialog"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerVertical="true"            android:text="Hello World!"            android:textColor="@android:color/white" />        <Button            android:id="@+id/send"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentRight="true"            android:text="发送" />    </RelativeLayout></LinearLayout>
使用很简单:

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();            }        });    }});
效果图如下:


原创粉丝点击