本文主要是介绍自定义仿IOS的圆角AlertDialog,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
以前都比较经常看别人写的博客,比较少动手写,最近有时间,觉得可以将工作中积累下来的一些知识点,经验什么的记录在博客中,
有助于自己理解,水平有限,希望能够逐渐提升自己的能力。
先上个效果图 ,也可以根据自己需求,添加控件,也可以根据这种思路,自己去修改布局文件。
首先在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" >
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- radius 为圆角半径 -->
<corners android:radius="20dp" ></corners>
<solid android:color="#ffffff" />
</shape>
<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_view_dialog_warm_tip" ><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添加进来。
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; }} }
然后是在activity中的代码,使用方法就跟alerdialog一样,具体的可以看源码。
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(); }
githup源码地址:
https://github.com/DarkSherlock/DialogBuilder
这篇关于自定义仿IOS的圆角AlertDialog的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!