Builder模式打造通用Dialog效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangwo1991/article/details/79477485
这是参照系统Dialog,采用Builder模式实现的一个万能dialog效果;

参照系统dialog的方式,涉及到AlertDialog、DialogViewHelper、AlertController这三个类, AlertDialog类中主要提供了一些dialog样式、效果、布局等设置的方法,采用Builder的设计模式,在使用的时候可以采用链式调用;
package com.dialogdemo.dialog;

import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;

import com.dialogdemo.R;

/**
 * Created by Administrator on 2017/5/21.
 * 自定义dialog
 */

public class AlertDialog extends Dialog {
    private AlertController mAlert;

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

    /**
     * 设置文本
     *
     * @param viewid
     * @param text
     */
    public void setText(int viewid, CharSequence text) {
        mAlert.setText(viewid, text);
    }

    public <T extends View> T getView(int viewid) {
        return mAlert.getView(viewid);
    }

    /**
     * 设置点击
     *
     * @param viewid
     * @param listener
     */
    public void setOnClickListener(int viewid, View.OnClickListener listener) {
        mAlert.setOnClickListener(viewid, listener);
    }

    public static class Builder {
        private AlertController.AlertParams P;

        public Builder(Context context) {
            this(context, R.style.dialog);//默认样式
        }

        public Builder(Context context, int themeResId) {
            P = new AlertController.AlertParams(context, themeResId);
        }

        public AlertDialog create() {
            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;
        }

        /**
         * 设置布局
         *
         * @param v
         * @return
         */
        public Builder setContentView(View v) {
            P.mView = v;
            P.mViewLayoutResId = 0;
            return this;
        }

        /**
         * 设置布局
         *
         * @param layoutId
         * @return
         */
        public Builder setContentView(int layoutId) {
            P.mView = null;
            P.mViewLayoutResId = layoutId;
            return this;
        }

        /**
         * 设置文本
         *
         * @param viewId
         * @param text
         * @return
         */
        public Builder setText(int viewId, CharSequence text) {
            P.mTextArray.put(viewId, text);
            return this;
        }

        /**
         * 设置点击
         *
         * @param view
         * @param listener
         * @return
         */
        public Builder setOnClickListener(int view, View.OnClickListener listener) {
            P.mClickArray.put(view, listener);
            return this;
        }
        //配置一些万能的参数

        /**
         * 全屏
         *
         * @return
         */
        public Builder fullWith() {
            P.mWith = ViewGroup.LayoutParams.MATCH_PARENT;
            return this;
        }

        /**
         * 从底部弹出是否有动画
         *
         * @param isAnimation
         * @return
         */
        public Builder formBottom(boolean isAnimation) {
            if (isAnimation) {
                P.mAnimation = R.style.dialog_from_bottom_anim;
            }
            P.mGravity = Gravity.BOTTOM;
            return this;
        }

        /**
         * 设置宽高
         *
         * @param with
         * @param height
         * @return
         */
        public Builder setWithAndHeight(int with, int height) {
            P.mWith = with;
            P.mHeight = height;
            return this;
        }

        /**
         * 添加默认动画
         *
         * @return
         */
        public Builder addDefaultAinmation() {
            P.mAnimation = R.style.dialog_scale_anim;
            return this;
        }

        /**
         * 添加动画
         *
         * @return
         */
        public Builder setAinmation(int styleAnimation) {
            P.mAnimation = styleAnimation;
            return this;
        }

        public Builder setOnCancelListener(OnCancelListener onCancelListener) {
            P.mOnCancelListener = onCancelListener;
            return this;
        }

        public Builder setOnDismissListener(OnDismissListener onDismissListener) {
            P.mOnDismissListener = onDismissListener;
            return this;
        }

        public Builder setOnKeyListener(OnKeyListener onKeyListener) {
            P.mOnKeyListener = onKeyListener;
            return this;
        }

        public Builder setCancelable(boolean cancelable) {
            P.mCancelable = cancelable;
            return this;
        }

        public AlertDialog show() {
            final AlertDialog dialog = create();
            dialog.show();
            return dialog;
        }
    }
}
AlertController类是万能dialog效果实现的一个控制类, AlertController类中有提供了一个AlertParams内部类,在AlertParams内部类的apply方法中进行dialog参数的绑定和设置;
package com.dialogdemo.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 Administrator on 2017/5/21.
 */

class AlertController {
    private AlertDialog mAlertDialog;
    private Window mWindow;
    private DialogViewHelper mViewHelper;

    /**
     * 获取AlertDialog
     *
     * @return
     */
    public AlertDialog getDialog() {
        return mAlertDialog;
    }

    /**
     * 获取AlertDialog的Window
     *
     * @return
     */
    public Window getWindow() {
        return mWindow;
    }

    public AlertController(AlertDialog alertDialog, Window window) {
        this.mAlertDialog = alertDialog;
        this.mWindow = window;
    }

    public void setViewHelper(DialogViewHelper mViewHelper) {
        this.mViewHelper = mViewHelper;
    }

    /**
     * 设置文本
     *
     * @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);
    }

    /**
     * 设置点击
     *
     * @param viewid
     * @param listener
     */
    public void setOnClickListener(int viewid, View.OnClickListener listener) {
        mViewHelper.setOnClickListener(viewid, listener);
    }

    public static class AlertParams {
        public Context mContext;
        public int mThemeResId;
        public boolean mCancelable = true;//点击空白是否可以取消
        public DialogInterface.OnCancelListener mOnCancelListener;//AlertDialog取消监听
        public DialogInterface.OnDismissListener mOnDismissListener;//AlertDialog消失监听
        public DialogInterface.OnKeyListener mOnKeyListener;//AlertDialog消失监听按键监听
        public View mView;//显示的布局
        public int mViewLayoutResId;//布局id
        //there can be gaps in the indices.  It is intended to be more memory efficient
        //* than using a HashMap to map Integers to Objects, both because it avoids
        //存放字体的修改
        public SparseArray<CharSequence> mTextArray = new SparseArray<CharSequence>();
        //存放点击事件
        public SparseArray<View.OnClickListener> mClickArray = new SparseArray<View.OnClickListener>();
        //默认宽度
        public int mWith = ViewGroup.LayoutParams.WRAP_CONTENT;
        //动画
        public int mAnimation = 0;
        //位置默认居中
        public int mGravity = Gravity.CENTER;
        //默认高度
        public int mHeight = ViewGroup.LayoutParams.WRAP_CONTENT;

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

        /**
         * 绑定和设置参数
         *
         * @param mAlert
         */
        public void apply(AlertController mAlert) {
            //设置参数
            //1设置布局
            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("viewHelper is null");
            }
            //给dialog设置布局
            mAlert.getDialog().setContentView(viewHelper.getContentView());

            //设置AlertController辅助类
            mAlert.setViewHelper(viewHelper);

            //2设置文本
            int mTextSize = mTextArray.size();
            for (int i = 0; i < mTextSize; i++) {
                mAlert.setText(mTextArray.keyAt(i), mTextArray.valueAt(i));
            }
            //3设置点击
            int mClickSize = mClickArray.size();
            for (int i = 0; i < mClickSize; i++) {
                mAlert.setOnClickListener(mClickArray.keyAt(i), mClickArray.valueAt(i));
            }

            //4设置自定效果  全屏   从底部弹出   默认动画
            Window window = mAlert.getWindow();
            //设置位置
            window.setGravity(mGravity);
            //设置动画
            if (mAnimation != 0) {
                window.setWindowAnimations(mAnimation);
            }
            //设置宽高
            WindowManager.LayoutParams attributes = window.getAttributes();
            attributes.width = mWith;
            attributes.height = mHeight;
            window.setAttributes(attributes);

        }
    }
}

最后剩下DialogViewHelper类,这个类比较简单,就是一个辅助类,用于布局的实例化加载,布局中view的缓存及设置一些点击事件等;

package com.dialogdemo.dialog;

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;

/**
 * Created by Administrator on 2017/5/21.
 * AlertDialog View 的辅助处理类
 */

class DialogViewHelper {
    private View mContentView = null;
    //用于缓存布局中的view
    private SparseArray<WeakReference<View>> mViews;

    public DialogViewHelper(Context mContext, int mViewLayoutResId) {
        this();
        //实例化解析加载布局文件
        mContentView = LayoutInflater.from(mContext).inflate(mViewLayoutResId, null);
    }

    public DialogViewHelper() {
        mViews = new SparseArray<>();
    }

    /**
     * 设置布局
     *
     * @param contentView
     */
    public void setContentView(View contentView) {
        this.mContentView = contentView;
    }

    /**
     * 设置文本
     *
     * @param viewid
     * @param text
     */
    public void setText(int viewid, CharSequence text) {
        TextView tv = getView(viewid);
        if (tv != null) {
            tv.setText("" + text);
        }
    }

    public <T extends View> T getView(int viewid) {
        WeakReference<View> viewWeakReference = mViews.get(viewid);
        View view = null;
        if (viewWeakReference != null) {
            view = viewWeakReference.get();
        }
        if (view == null) {
            view = mContentView.findViewById(viewid);
            if (view != null) {
                mViews.put(viewid, new WeakReference<View>(view));
            }
        }
        return (T) view;
    }

    /**
     * 设置点击
     *
     * @param viewid
     * @param listener
     */
    public void setOnClickListener(int viewid, View.OnClickListener listener) {
        View view = getView(viewid);
        if (view != null) {
            view.setOnClickListener(listener);
        }
    }

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

接下来说下简单的调用:

private void thridView() {
        List<String> list = new ArrayList();
        for (int i = 0; i < 5; i++) {
            list.add("item" + i);
        }
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setContentView(R.layout.thrid_layout)
                .setCancelable(true)
                .show();
        RecyclerView recyclerView = dialog.getView(R.id.recycler_view);
        //设置布局管理器
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        DialogListAdapter adapter = new DialogListAdapter(list, this);
        recyclerView.setAdapter(adapter);
    }
这样就实现了dialog列表的效果,是不是感觉调用很简单。
源码地址:
https://pan.baidu.com/s/1MuJcrcBYLox4dFud_tJ9kg

猜你喜欢

转载自blog.csdn.net/wangwo1991/article/details/79477485