美文网首页
简洁仿IOS的圆角Dialog

简洁仿IOS的圆角Dialog

作者: 我喂自己袋丶夏洛克 | 来源:发表于2017-08-17 16:39 被阅读0次

    先上个效果图 ,也可以根据自己需求,添加控件,也可以根据这种思路,自己去修改布局文件。

    最后会给出源码githup地址。


    然后开始吧。
    首先在styles文件里定义样式。

    <style name="AlertDialogStyle" parent="@android:style/Theme.Dialog">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowFrame">@null</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsTranslucent">true</item>
    </style>
    

    接着再drawable文件夹下自定义一个圆角的shape.

    <?xml version="1.0" encoding="utf-8"?>
    
    <shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- radius 为圆角半径  -->
    
        <corners android:radius="20dp" ></corners>
    
        <solid android:color="#ffffff" />
    
    </shape>
    

    然后自定义一个dialog的xml布局, 并且设置背景引用圆角shape。
    android:background="@drawable/bg_course_dialog"
    布局文件代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    xmlns:tools="http://schemas.android.com/tools"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="@drawable/bg_course_dialog"
        >
    
    
        <ImageView
            android:id="@+id/icon"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_marginTop="28dp"
            android:layout_toLeftOf="@+id/title"
            android:src="@mipmap/ic_launcher_round"
            android:visibility="gone"
            />
    
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="25dp"
            android:textColor="#000000"
            android:textSize="20sp"
            android:textStyle="bold"
            tools:text="titletitletitle"
            />
    
        <LinearLayout
            android:id="@+id/ll_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/title"
            android:layout_gravity="center_horizontal"
            android:layout_marginBottom="25dp"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:layout_marginTop="5dp"
            android:gravity="center"
            android:orientation="vertical"
            >
    
            <TextView
                android:id="@+id/message"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#000000"
                android:textSize="16sp"
                tools:text="message"/>
        </LinearLayout>
    
    
        <View
            android:id="@+id/line_horizontal"
            android:layout_width="match_parent"
            android:layout_height="0.5dp"
            android:layout_below="@+id/ll_content"
            android:visibility="gone"
            android:background="#dad6d6"/>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/line_horizontal"
            android:orientation="horizontal">
    
            <TextView
                android:id="@+id/dialog_cancel"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginBottom="8dp"
                android:layout_marginTop="8dp"
                android:layout_weight="1"
                android:clickable="true"
                android:gravity="center"
                android:text="取消"
                android:textColor="#007aff"
                android:textSize="18sp"
                android:visibility="gone"/>
    
            <View
                android:id="@+id/line_vertical"
                android:layout_width="0.5dp"
                android:layout_height="match_parent"
                android:background="#dad6d6"
                android:visibility="gone"/>
    
            <TextView
                android:id="@+id/dialog_commit"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginBottom="8dp"
                android:layout_marginTop="8dp"
                android:layout_weight="1"
                android:gravity="center"
                android:text="确认"
                android:textColor="#007aff"
                android:textSize="18sp"
                android:visibility="gone"/>
        </LinearLayout>
    
    </RelativeLayout>
    

    然后是封装的具体代码。
    这里使用alertdialog中的建造者模式Builder来建造,这样可以方便我们建造不同需求的dialog。(如对建造者模式不了解的可以自己搜一下相关资料)

    代码很简单 首先是构造一个Params来管理我们具体要build的属性。

    public static class Builder implements BuilderInterface {
        private Context mContext;
        private final ControllerParams mParams;
        private Controller mController;
    
        public Builder(Context context) {
            mContext = context;
            mParams = new ControllerParams();
            mController = new Controller(mContext);
        }
    
        public Builder setContentView(int layoutId) {
            mParams.setLayoutId(layoutId);
            return this;
        }
    
        public Builder setContentView(View view) {
            mParams.setContentView(view);
            return this;
        }
    
        public Builder setTitle(String title) {
            mParams.setTitle(title);
            return this;
        }
    
        public Builder reSetTitle(String title) {
            mParams.setTitle(title);
            mController.setTitle(title);
            return this;
        }
    
        public Builder reSetMessage(String message) {
            mParams.setMessage(message);
            mController.setMessage(message);
            return this;
        }
    
        public Builder reSetIcon(int iconId) {
            mParams.setIconId(iconId);
            mController.setIcon(iconId);
            return this;
        }
    
        public Builder setMessage(String message) {
            mParams.setMessage(message);
            return this;
        }
    
        public Builder setIcon(int iconId) {
            mParams.setIconId(iconId);
            return this;
        }
    
        public Builder setCancelable(boolean cancelable) {
            mParams.setCancelable(cancelable);
            return this;
        }
    
    
        public Builder setNegativeButton(String text, OnNegativeListener listener) {
            mParams.setNegativeListener(listener);
            mParams.setNegativeText(text);
    
            return this;
        }
    
        public Builder setPositiveButton(String text,  OnPositiveListener listener)  {
            mParams.setPositiveListener(listener);
            mParams.setPositiveText(text);
            return this;
        }
    
        /**
         * 建造dialog
         * @return dialog
         */
        public Dialog create() {
            Dialog dialog = new Dialog(mContext, R.style.AlertDialogStyle);
            //属性交给controller去应用到dialog上
            mParams.apply(mController, dialog);
            return dialog;
        }
    
        /**
         * 建造一个默认的dialog
         * @param onPositiveListener 确认按键监听
         * @param onNegativeListener 取消按键监听
         * @return dialog
         */
        public Dialog createDefault(OnPositiveListener onPositiveListener, OnNegativeListener onNegativeListener) {
            Dialog dialog = new Dialog(mContext, R.style.AlertDialogStyle);
            build(onPositiveListener, onNegativeListener);
            mParams.apply(mController, dialog);
            return dialog;
        }
    
        private void build(OnPositiveListener onPositiveListener, OnNegativeListener onNegativeListener) {
            setTitle("温馨提示")
                    .setMessage("确认提交吗")
                    .setCancelable(false)
                    .setPositiveButton("确认", onPositiveListener)
                    .setNegativeButton("取消", onNegativeListener);
        }
    }
    

    管理属性的类核心方法就是apply(),在这里判断是否缓存了属性,有的话就交给controller去设置给dialog.

    /**
     * 管理dialog所有属性的类
     */
    private static class ControllerParams {
        private String mTitle;
        private String mMessage;
        private int mIconId = -1;
        private int mLayoutId = -1;
        private boolean mCancelable;
        private String mPositiveText;
        private String mNegativeText;
        private OnPositiveListener mPositiveListener;
        private OnNegativeListener mNegativeListener;
        private View mContentView;
    
    
        private void apply(Controller controller, Dialog dialog) {
    
            if (mContentView != null) {
                controller.setContentView(mContentView, dialog);
            }else {
                controller.setContentView(mLayoutId, dialog);
            }
            dialog.setCancelable(mCancelable);
            if (mCancelable) {
                dialog.setCanceledOnTouchOutside(true);
            }
    
            if (mTitle != null) {
                controller.setTitle(mTitle);
            }
            if (mMessage != null) {
                controller.setMessage(mMessage);
            }
            if (mPositiveText != null && mPositiveListener != null) {
                controller.setPositiveButton(mPositiveText, mPositiveListener);
            }
            if (mNegativeText != null && mNegativeListener != null) {
                controller.setNegativeButton(mNegativeText, mNegativeListener);
            }
            if (mIconId != -1) {
                controller.setIcon(mIconId);
            }
    
    
        }
    
    
        public int getLayoutId() {
            return mLayoutId;
        }
    
        private void setLayoutId(int layoutId) {
            mLayoutId = layoutId;
        }
    
        public String getTitle() {
            return mTitle;
        }
    
        private void setTitle(String title) {
            mTitle = title;
        }
    
        public String getMessage() {
            return mMessage;
        }
    
        private void setMessage(String message) {
            mMessage = message;
        }
    
        public int getIconId() {
            return mIconId;
        }
    
        private void setIconId(int iconId) {
            mIconId = iconId;
        }
    
        public boolean isCancelable() {
            return mCancelable;
        }
    
        private void setCancelable(boolean cancelable) {
            mCancelable = cancelable;
        }
    
        public String getPositiveText() {
            return mPositiveText;
        }
    
        private void setPositiveText(String positiveText) {
            mPositiveText = positiveText;
        }
    
        public String getNegativeText() {
            return mNegativeText;
        }
    
        private void setNegativeText(String negativeText) {
            mNegativeText = negativeText;
        }
    
        public OnPositiveListener getPositiveListener() {
            return mPositiveListener;
        }
    
        private void setPositiveListener(OnPositiveListener positiveListener) {
            mPositiveListener = positiveListener;
        }
    
        public OnNegativeListener getNegativeListener() {
            return mNegativeListener;
        }
    
        private void setNegativeListener(OnNegativeListener negativeListener) {
            mNegativeListener = negativeListener;
        }
    
        private void setContentView(View contentView) {
            mContentView = contentView;
        }
    }
    

    这里定义2个点击监听,用来回调dialog中确认和取消的点击。

    /**
     * 确认按键监听
     */
    public interface OnPositiveListener {
        void onPositive(Dialog dialog);
    
    }
    
    /**
     * 取消按键监听
     */
    public interface OnNegativeListener {
        void onNegative(Dialog dialog);
    }
    

    这里controller中封装了最主要的代码,代码很简单,就是将上面写的dialog的 xml布局文件inflate出来设置给dialog,这也是封装好的默认的dialog 就跟一开始的效果图一样。
    但是我们说了,我们有可能有其他需求,这时候就需要用builder.setcontentview将我们需要的具体的view或者layoutid传进来,这时候看代码,我们布局文件中的根布局ll_content就会将默认的message的textview remove掉,然后再把传进来的view添加进来,这就实现定制其他需求的View。

    private static class Controller implements View.OnClickListener,BuilderInterface {
        private Context mContext;
        private TextView mTvTitle;
        private TextView mTvMessage;
        private TextView mTvPositive;
        private TextView mTvNegative;
        private ImageView mIvIcon;
        private View mHorizontalLine;
        private View mVerticalLine;
        private View mRootView;
        private OnNegativeListener mOnNegativeListener;
        private OnPositiveListener mOnPositiveListener;
        private Dialog mDialog;
        private View mContentView;
        private final LinearLayout mLlContent;
    
    
        private   Controller(Context context) {
            mContext = context;
            mRootView = View.inflate(mContext, R.layout.view_dialog_warm_tip, null);
            mLlContent = (LinearLayout) mRootView.findViewById(R.id.ll_content);
            mHorizontalLine = mRootView.findViewById(R.id.line_horizontal);
        }
    
        private void setContentView(int layoutResID, Dialog dialog) {
            if (layoutResID == -1) {
    
            } else {
                mContentView = View.inflate(mContext, layoutResID, null);
                mLlContent.removeAllViews();
                mLlContent.addView(mContentView);
            }
            mDialog = dialog;
            dialog.setContentView(mRootView, getPrams(mContext));
        }
    
        private void setContentView(View view, Dialog dialog) {
            mLlContent.removeAllViews();
            mLlContent.addView(view);
            mDialog = dialog;
            dialog.setContentView(mRootView, getPrams(mContext));
        }
    
        private FrameLayout.LayoutParams getPrams(Context context) {
            WindowManager windowManager = (WindowManager) context
                    .getSystemService(Context.WINDOW_SERVICE);
            Display sDefaultDisplay = windowManager.getDefaultDisplay();
    
            return new FrameLayout.LayoutParams(
                    (int) (sDefaultDisplay.getWidth() * 0.80f),
                    ViewGroup.LayoutParams.WRAP_CONTENT);
    
        }
    
    
        public Controller setTitle(String title) {
            mTvTitle = (TextView) mRootView.findViewById(R.id.title);
            if (mTvTitle != null) {
                mTvTitle.setText(title);
            }
            return this;
        }
    
        public Controller setMessage(String message) {
            mTvMessage = (TextView) mRootView.findViewById(R.id.message);
            if (mTvMessage != null) {
                mTvMessage.setText(message);
            }
            return this;
        }
    
        public Controller setIcon(int iconId) {
            mIvIcon = (ImageView) mRootView.findViewById(R.id.icon);
            if (mIvIcon != null) {
                mIvIcon.setImageResource(iconId);
                mIvIcon.setVisibility(View.VISIBLE);
            }
            return this;
        }
    
        @Override
        public BuilderInterface setCancelable(boolean cancelable) {
            return null;
        }
    
    
        public Controller setNegativeButton(String negativeText, OnNegativeListener listener) {
            mTvNegative = (TextView) mRootView.findViewById(R.id.dialog_cancel);
            mVerticalLine = mRootView.findViewById(R.id.line_vertical);
            if (mTvNegative != null) {
                mTvNegative.setVisibility(View.VISIBLE);
                mTvNegative.setText(negativeText);
                setOnNegativeListener(listener);
                mHorizontalLine.setVisibility(View.VISIBLE);
                if (mTvPositive != null) {
                    mVerticalLine.setVisibility(View.VISIBLE);
                }
    
            }
            return this;
        }
    
        public Controller setPositiveButton(String positiveText, OnPositiveListener listener) {
            mTvPositive = (TextView) mRootView.findViewById(R.id.dialog_commit);
    
            if (mTvPositive != null) {
                mTvPositive.setVisibility(View.VISIBLE);
                mTvPositive.setText(positiveText);
                setOnPositiveListener(listener);
                mHorizontalLine.setVisibility(View.VISIBLE);
            }
            return this;
        }
    
        private Controller setOnNegativeListener(OnNegativeListener onNegativeListener) {
    
            mOnNegativeListener = onNegativeListener;
            mTvNegative.setOnClickListener(this);
            return this;
        }
    
        private Controller setOnPositiveListener(OnPositiveListener onPositiveListener) {
    
            mOnPositiveListener = onPositiveListener;
            mTvPositive.setOnClickListener(this);
            return this;
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.dialog_cancel:
                    if (mOnNegativeListener != null) {
                        mOnNegativeListener.onNegative(mDialog);
                    }
                    break;
                case R.id.dialog_commit:
                    if (mOnPositiveListener != null) {
                        mOnPositiveListener.onPositive(mDialog);
                    }
                    break;
            }
        }
    }
    

    到这里dialog的封装就完了,接下来看看activity中怎么使用。
    使用方法就跟alertdialog一样。

     private void initDefaultDialog() {
            SherlockDialog.Builder builder = new SherlockDialog.Builder(this);
            mDialog = builder.createDefault(this, this);
    //        builder.reSetTitle("重新设置Tiltle");
        }
    
        private void initEditDialog() {
            SherlockDialog.Builder builder = new SherlockDialog.Builder(this);
    
            EditText editText = new EditText(this);
            builder.setContentView(editText);
            mDialog = builder.createDefault(this, this);
    
        }
    
        private void initDialog() {
    
            SherlockDialog.Builder builder = new SherlockDialog.Builder(this);
            mDialog = builder.setTitle("温馨提示")
                    .setMessage("确认提交吗?")
                    .setPositiveButton("确认", new SherlockDialog.OnPositiveListener() {
                        @Override
                        public void onPositive(Dialog dialog) {
                            Toast.makeText(DialogActivity.this, "确认提交", Toast.LENGTH_SHORT).show();
                            dialog.dismiss();
                        }
                    })
                    .setNegativeButton("取消", new SherlockDialog.OnNegativeListener() {
                        @Override
                        public void onNegative(Dialog dialog) {
                            Toast.makeText(DialogActivity.this, "取消提交", Toast.LENGTH_SHORT).show();
                            dialog.dismiss();
                        }
                    })
                    .setIcon(R.mipmap.ic_launcher_round).create();
        }
    
        public void button1(View view) {
            initDialog();
            mDialog.show();
        }
    
        public void button2(View view) {
    
            initEditDialog();
            mDialog.show();
        }
    
        public void button3(View view) {
            initDefaultDialog();
            mDialog.show();
        }
    
        @Override
        public void onPositive(Dialog dialog) {
            dialog.dismiss();
        }
    
        @Override
        public void onNegative(Dialog dialog) {
            dialog.dismiss();
        }
    

    可以看到跟系统自带的alertdialog的builder方法使用是一样的。

    githup源码地址:
    https://github.com/DarkSherlock/DialogBuilder

    相关文章

      网友评论

          本文标题:简洁仿IOS的圆角Dialog

          本文链接:https://www.haomeiwen.com/subject/ktknrxtx.html