一、自定义弹窗基础
自定义弹窗通常由布局文件、弹窗类和调用代码三部分组成。
1、布局文件
我们可以在res/layout目录下创建XML布局文件,设置弹窗的外观、控件和事件响应等。例如,下面的示例布局文件设置了一个包含TextView和Button的弹窗:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_dialog_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="@+id/dialog_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="@color/colorPrimary"
android:text="弹窗标题" />
<TextView
android:id="@+id/dialog_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="弹窗消息" />
<Button
android:id="@+id/dialog_button_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="取消"
android:textColor="@color/colorPrimary" />
<Button
android:id="@+id/dialog_button_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="确定"
android:textColor="@color/colorAccent" />
</LinearLayout>
2、弹窗类
我们需要创建一个自定义的弹窗类,继承Dialog类或其子类,重载构造函数以及实现必要的弹窗逻辑。例如,下面示例代码创建一个继承自Dialog的CustomDialog类,并为其中的Button设置点击事件:
public class CustomDialog extends Dialog implements View.OnClickListener {
private TextView mTitle;
private TextView mMessage;
private Button mButtonCancel;
private Button mButtonOk;
private OnClickListener mOnClickListener;
public CustomDialog(Context context) {
this(context, R.style.Theme_CustomDialog);
}
public CustomDialog(Context context, int themeResId) {
super(context, themeResId);
setContentView(R.layout.dialog_custom_layout);
setCancelable(false);
mTitle = findViewById(R.id.dialog_title);
mMessage = findViewById(R.id.dialog_message);
mButtonCancel = findViewById(R.id.dialog_button_cancel);
mButtonOk = findViewById(R.id.dialog_button_ok);
mButtonCancel.setOnClickListener(this);
mButtonOk.setOnClickListener(this);
}
public CustomDialog setTitle(String title) {
mTitle.setText(title);
return this;
}
public CustomDialog setMessage(String message) {
mMessage.setText(message);
return this;
}
public CustomDialog setOnClickListener(OnClickListener onClickListener) {
mOnClickListener = onClickListener;
return this;
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.dialog_button_cancel) {
dismiss();
if (mOnClickListener != null) {
mOnClickListener.onNegativeClick();
}
} else if (id == R.id.dialog_button_ok) {
dismiss();
if (mOnClickListener != null) {
mOnClickListener.onPositiveClick();
}
}
}
public interface OnClickListener {
void onNegativeClick();
void onPositiveClick();
}
}
3、调用代码
我们可以在Activity或Fragment中调用自定义的弹窗类,设置弹窗的标题、消息和点击响应等。例如,下面示例代码创建一个CustomDialog并弹出:
CustomDialog dialog = new CustomDialog(this)
.setTitle("提示")
.setMessage("是否保存当前内容?")
.setOnClickListener(new CustomDialog.OnClickListener() {
@Override
public void onNegativeClick() {
// 取消操作
}
@Override
public void onPositiveClick() {
// 确认操作
}
});
dialog.show();
二、弹窗功能扩展
除了基础的弹窗功能,我们可以通过继续扩展弹窗类的特性,增强弹窗的功能和灵活性。
1、多按钮弹窗
多按钮弹窗可以让用户在不同的选项中进行选择。我们可以通过在自定义的弹窗布局文件中添加多个Button元素,以及在弹窗类中添加响应事件的处理逻辑。例如,下面的代码实现了包含三个按钮的CustomDialog:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_dialog_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="@+id/dialog_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="@color/colorPrimary"
android:text="弹窗标题" />
<TextView
android:id="@+id/dialog_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="弹窗消息" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<Button
android:id="@+id/dialog_button_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消"
android:textColor="@color/colorPrimary"
android:layout_marginRight="20dp" />
<Button
android:id="@+id/dialog_button_ignore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="忽略"
android:textColor="@color/colorAccent"
android:layout_marginRight="20dp" />
<Button
android:id="@+id/dialog_button_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确定"
android:textColor="@color/colorAccent" />
</LinearLayout>
</LinearLayout>
public class CustomDialog extends Dialog implements View.OnClickListener {
private TextView mTitle;
private TextView mMessage;
private Button mButtonCancel;
private Button mButtonIgnore;
private Button mButtonOk;
private OnClickListener mOnClickListener;
public CustomDialog(Context context) {
this(context, R.style.Theme_CustomDialog);
}
public CustomDialog(Context context, int themeResId) {
super(context, themeResId);
setContentView(R.layout.dialog_custom_layout);
setCancelable(false);
mTitle = findViewById(R.id.dialog_title);
mMessage = findViewById(R.id.dialog_message);
mButtonCancel = findViewById(R.id.dialog_button_cancel);
mButtonIgnore = findViewById(R.id.dialog_button_ignore);
mButtonOk = findViewById(R.id.dialog_button_ok);
mButtonCancel.setOnClickListener(this);
mButtonIgnore.setOnClickListener(this);
mButtonOk.setOnClickListener(this);
}
// 省略部分代码
}
2、列表弹窗
列表弹窗可以让用户在一个列表中选择一个选项。我们可以通过在自定义的弹窗布局文件中添加ListView元素,以及在弹窗类中添加适配器和点击事件的处理逻辑。例如,下面的代码实现了包含三个列表项的CustomListDialog:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_dialog_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="@+id/dialog_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="@color/colorPrimary"
android:text="弹窗标题" />
<ListView
android:id="@+id/dialog_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@color/gray"
android:dividerHeight="1dp" />
<Button
android:id="@+id/dialog_button_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="取消"
android:textColor="@color/colorPrimary"
android:layout_marginTop="20dp" />
</LinearLayout>
public class CustomListDialog extends Dialog implements AdapterView.OnItemClickListener, View.OnClickListener {
private TextView mTitle;
private ListView mListView;
private Button mButtonCancel;
private List
mItemList;
private OnItemClickListener mOnItemClickListener;
public CustomListDialog(Context context, List
itemList) {
super(context, R.style.Theme_CustomDialog);
setContentView(R.layout.dialog_custom_list_layout);
setCancelable(false);
mTitle = findViewById(R.id.dialog_title);
mListView = findViewById(R.id.dialog_list_view);
mButtonCancel = findViewById(R.id.dialog_button_cancel);
mButtonCancel.setOnClickListener(this);
mItemList = itemList;
ArrayAdapter
adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, itemList);
mListView.setAdapter(adapter);
mListView.setOnItemClickListener(this);
}
public CustomListDialog setTitle(String title) {
mTitle.setText(title);
return this;
}
public CustomListDialog setOnItemClickListener(OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
return this;
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.dialog_button_cancel) {
dismiss();
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String item = mItemList.get(position);
dismiss();
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemClick(item);
}
}
public interface OnItemClickListener {
void onItemClick(String item);
}
}
3、自动消失弹窗
自动消失弹窗可以在显示一定时间后自动消失,避免用户没有及时关闭弹窗,从而对用户造成影响。我们可以在弹窗类中添加计时器和相关的判断逻辑。例如,下面的代码实现了一个3秒后自动消失的CustomAutoDismissDialog:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_dialog_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="@+id/dialog_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="@color/colorPrimary"
android:text="弹窗标题" />
<TextView
android:id="@+id/dialog_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="弹窗消息" />
</LinearLayout>
public class CustomAutoDismissDialog extends Dialog {
private TextView mTitle;
private TextView mMessage;
private Handler mHandler = new Handler();
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
dismiss();
}
};
public CustomAutoDismissDialog(Context context) {
this(context, R.style.Theme_CustomDialog);
}
public CustomAutoDismissDialog(Context context, int themeResId) {
super(context, themeResId