您的位置:首页 > 移动开发 > IOS开发

自定义仿IOS的圆角AlertDialog

2016-12-14 13:55 225 查看
以前都比较经常看别人写的博客,比较少动手写,最近有时间,觉得可以将工作中积累下来的一些知识点,经验什么的记录在博客中,
有助于自己理解,水平有限,希望能够逐渐提升自己的能力。

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



首先在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布局, 并且设置背景引用圆角shapeandroid: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 dialog