文章目录
前言
今天完成了之前界面课程详情页的撰写。开始写新的界面及其逻辑,其中用到了Dialog,于是开始学习Dialog,公司做法是自定义一个新类继承自Dialog,使用新布局作为这个Dialog的样子。然后每次新建这个新类,并同时设置Dialog中两个按钮的监听器。如果大家有这个基础,直接去看自定义布局,为了防止csdn下载需要积分,我直接把代码全贴出来。
界面类似于:
接下来要学习一下关于Dialog的用法。首先还是放几篇好文章:
1.Android Dialog的官方教程
2.android 8种对话框(Dialog)使用方法汇总
官方的教程就是给力。
Dialog是对话框的基类,但您应该避免直接实例化 Dialog,而是使用下列子类之一:
AlertDialog
此对话框可显示标题、最多三个按钮、可选择项列表或自定义布局。
DatePickerDialog 或 TimePickerDialog
此对话框带有允许用户选择日期或时间的预定义 UI。
Android 包括另一种名为 ProgressDialog 的对话框类,可显示具有进度条的对话框。不过,如需指示加载进度或不确定的进度,则应改为遵循进度和 Activity 的设计指南,并在您的布局中使用 ProgressBar。
注意事项
1.这是错误的获取context方式。
final AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
应该直接传入当前所在的Activity
final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
使用可输入的Dialog
public void showEditDialog()
{
final EditText inputServer = new EditText(this);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Edit Dialog").setIcon(android.R.drawable.ic_dialog_info).setView(inputServer)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this,"你取消是干啥玩意?",
Toast.LENGTH_SHORT).show();
}
});
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,inputServer.getText().toString(),
Toast.LENGTH_SHORT).show();
}
});
builder.show();
}
普通弹出框
public void showNormalDialog()
{
/* @setIcon 设置对话框图标
* @setTitle 设置对话框标题
* @setMessage 设置对话框消息提示
* setXXX方法返回Dialog对象,因此可以链式设置属性
*/
final AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this);
builder.setIcon(R.mipmap.ic_launcher);
builder.setTitle("普通弹出框");
builder.setMessage("是否继续");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this,"点击了确定",Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this,"点击了取消",Toast.LENGTH_SHORT).show();
}
});
builder.setNeutralButton("中间的",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"点击了中间的",Toast.LENGTH_SHORT).show();
}
});
builder.create().show();
}
列表选择框、单选框、多选框
列表选择框就使用如下方法
builder.setItems(@ArrayRes int itemsId, OnClickListener listener)
要想添加多选项(复选框)或单选项(单选按钮)列表,请分别使用 setMultiChoiceItems() 或 setSingleChoiceItems() 方法。
以下示例展示了如何创建如图 所示的多选列表,将选定项保存在一个 ArrayList 中:
在onClick中,判断是否被选择,如果被点击就添加选中的值,如果没被选中就判断该值是否在ArrayList中,如果在的话就去掉它。
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mSelectedItems = new ArrayList(); // Where we track the selected items
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Set the dialog title
builder.setTitle(R.string.pick_toppings)
// Specify the list array, the items to be selected by default (null for none),
// and the listener through which to receive callbacks when items are selected
.setMultiChoiceItems(R.array.toppings, null,
new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
if (isChecked) {
// If the user checked the item, add it to the selected items
mSelectedItems.add(which);
} else if (mSelectedItems.contains(which)) {
// Else, if the item is already in the array, remove it
mSelectedItems.remove(Integer.valueOf(which));
}
}
})
// Set the action buttons
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// User clicked OK, so save the mSelectedItems results somewhere
// or return them to the component that opened the dialog
...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
...
}
});
return builder.create();
}
public void showListDialog()
{
choice = -1;
final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("选择一个月份")
//这里的第二个参数是被选中的Item。
.setSingleChoiceItems(R.array.months, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
choice=i;
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (choice != -1) {
String month=MainActivity.this.getResources().
getStringArray(R.array.months)[choice];
Toast.makeText(MainActivity.this,month,
Toast.LENGTH_SHORT).show();
}
}
});
builder.create().show();
}
自定义布局
如果您想让对话框具有自定义布局,请创建一个布局,然后通过调用 AlertDialog.Builder 对象上的 setView() 将其添加到 AlertDialog。
默认情况下,自定义布局会填充对话框窗口,但您仍然可以使用 AlertDialog.Builder 方法来添加按钮和标题。
我们也可以完全自已定义一个Dialog。
定义Dialog需要有以下几步。
1. 定义一个style
这个style是用作给Dialog设置的,会在构造函数使用。
<style name="InfoEditDialog" parent="android:Theme.Dialog">
<!-- 背景颜色及透明程度 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 是否半透明 -->
<item name="android:windowIsTranslucent">false</item>
<!-- 是否没有标题 -->
<item name="android:windowNoTitle">true</item>
<!-- 是否浮现在activity之上 -->
<item name="android:windowIsFloating">true</item>
<!-- 是否背景模糊 -->
<item name="android:backgroundDimEnabled">false</item>
<!-- 设置背景模糊的透明度-->
<item name="android:backgroundDimAmount">0.5</item>
</style>
构造函数
public InfoEditDialog(Context mContext)
{
super(mContext,R.style.InfoEditDialog);
//this.mContext=mContext;
initView(mContext);
}
2. 定义一个xml文件
这个xml文件是作为Dialog的默认内容xml。大概样子就是这样的,包含两个EditText与两个Button。
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/info_edit_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/verify_dialog_background"
android:padding="10dp"
>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="弹出框"
android:textSize="30dp"
android:gravity="center"
/>
<EditText
android:id="@+id/bank_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入您的银行卡号"
android:layout_below="@+id/title"
/>
<EditText
android:id="@+id/id_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入您的身份证"
android:layout_below="@+id/bank_card"
/>
<Button
android:id="@+id/positive_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/id_card"
android:layout_toLeftOf="@+id/negative_button"
/>
<Button
android:id="@+id/negative_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/id_card"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
3.InfoEditDialog类
这里其实对我来说的难点就是Button的点击事件,因为其他的要写的话就是一些set和get函数。我先写一下Button的点击事件处理。比较麻烦的问题在于,你setButton时,set的linstener不是View.OnclickListener,而是DialogInterface.OnClickListener。
首先定义两个listener,
private DialogInterface.OnClickListener mPositiveListener, mNegativeListener;
之后获取两个button的id
btn_negavite=findViewById(R.id.negative_button);
btn_positive=findViewById(R.id.positive_button);
两个listener会在setPositiveButton与setNegaviteButton时被设置。getButton()函数是获取两个button的id。setNegaviteButton会在我们使用这个Dialog的地方被调用,往往都是重新实现一下DialogInterface.OnClickListener这个接口的实例,然后将text和实例一同传入函数。
public Button getButton(int whichButton) {
switch (whichButton) {
case BUTTON_POSITIVE:
return btn_positive;
case BUTTON_NEUTRAL:
return null;
case BUTTON_NEGATIVE:
return btn_negavite;
}
return null;
}
public void setNegaviteButton(CharSequence text,DialogInterface.OnClickListener listener){
Button button = getButton(BUTTON_NEGATIVE);
if (button != null)
{
button.setText(text);
mNegativeListener=listener;
}
}
这里举一个在Activity中的实例。
infoEditDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String editText =infoEditDialog.getFirstEditString();
Toast.makeText(MainActivity.this,editText,Toast.LENGTH_SHORT).show();
}
});
之后会设置两个button的OnClickListener。这里设置的OnClickListener是View.OnClickListener这个接口。这里其实只是写个过程,但这一步的代码,其实和之前设置id都是放在一起的。
btn_positive.setOnClickListener(mViewClickListener);
btn_negavite.setOnClickListener(mViewClickListener);
这个mViewClickListener是我们的一个对象。这个实现的是 View.OnClickListener接口,dismiss函数就是说点击这个button可以退出dialog。在这个接口对象中我们判断究竟是哪个button,并在该button的点击事件中调用最先定义的两个DialogInterface.OnClickListener对象的Onclick函数。
private View.OnClickListener mViewClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (v == btn_positive) {
/*
if (mIsAutoDismiss)
dismiss();*/
dismiss();
if (mPositiveListener != null)
mPositiveListener.onClick(InfoEditDialog.this, DialogInterface.BUTTON_POSITIVE);
} else if (v == btn_negavite) {
dismiss();
if (mNegativeListener != null)
mNegativeListener.onClick(InfoEditDialog.this, DialogInterface.BUTTON_NEGATIVE);
}
}
};
在稍微写一下获取两个EditText的方法。
public String getFirstEditString()
{
String firstEditString = edit_bank_card.getText().toString();
if (!("".equals(firstEditString))&&firstEditString.length()>0)
return firstEditString;
else
return "你啥都没写返回尼玛阿";
}
public String getSecondEditString()
{
String secondEditString = edit_id_card.getText().toString();
// if (secondEditString!=null)
return secondEditString;
}
之后另一个需要注意的就是要创建一个内部类Builder,这是一种设计模式。这里先把我的Builder代码放出来。
public static class Builder{
protected Context mContext;
CharSequence title,firstEditText,secondEditText;
CharSequence positiveButtonText, negativeButtonText;
DialogInterface.OnClickListener positiveButtonListener, negativeButtonListener;
InfoEditDialog dialog;
boolean cancelable = true;
boolean cancelableTouchOutside = true;
OnCancelListener onCancelListener;
OnKeyListener onKeyListener;
View customView;
public Builder(Context context){mContext=context;}
public Builder setTitle(int titleId) {
title = mContext.getText(titleId);
return this;
}
public Builder setTitle(CharSequence title) {
this.title = title;
return this;
}
public Builder setFirstEditText(CharSequence firstEditText) {
this.firstEditText = firstEditText;
return this;
}
public Builder setFirstEditTexr(int rid){
this.firstEditText = mContext.getText(rid);
return this;
}
public Builder setSecondEditText(CharSequence secondEditText) {
this.secondEditText = secondEditText;
return this;
}
public Builder setSecondEditText(int rid){
this.secondEditText = mContext.getText(rid);
return this;
}
public Builder setPositiveButton(CharSequence text,DialogInterface.OnClickListener listener)
{
this.positiveButtonText = text;
this.positiveButtonListener = listener;
return this;
}
public Builder setNegativeButton(CharSequence text,DialogInterface.OnClickListener listener){
this.negativeButtonText = text;
this.negativeButtonListener = listener;
return this;
}
public Builder setCustomView(View customView) {
this.customView = customView;
return this;
}
public Builder setCancelable(boolean cancelable) {
this.cancelable = cancelable;
return this;
}
public Builder setCancelableTouchOutside(boolean cancelableTouchOutside){
this.cancelableTouchOutside = cancelableTouchOutside;
return this;
}
public Builder setOnCancelListener(OnCancelListener onCancelListener) {
this.onCancelListener = onCancelListener;
return this;
}
public Builder setOnKeyListener(OnKeyListener onKeyListener) {
this.onKeyListener = onKeyListener;
return this;
}
public String getFirstEditText() {
return dialog.getFirstEditString();
}
public String getSecondEditText(){
return dialog.getSecondEditString();
}
public InfoEditDialog create(){
final InfoEditDialog d = new InfoEditDialog(mContext);
d.setTitle(title);
//这里可以不设置listener
if (positiveButtonText!=null)
d.setPositiveButton(positiveButtonText,positiveButtonListener);
if (negativeButtonText!=null)
d.setNegaviteButton(negativeButtonText,negativeButtonListener);
if (firstEditText!=null)
d.setFirstEditText(firstEditText);
if (secondEditText!=null)
d.setSecondEdit(secondEditText);
d.setCancelable(cancelable);
d.setOnCancelListener(onCancelListener);
d.setCanceledOnTouchOutside(cancelableTouchOutside);
if (onKeyListener!=null)
{
d.setOnKeyListener(onKeyListener);
}
return d;
}
public InfoEditDialog show(){
dialog = create();
dialog.show();
return dialog;
}
public void dismiss()
{
dialog.dismiss();
}
}
我在Activity是这样调用的。
public void showInfoEditDialogInBuilder() {
final InfoEditDialog.Builder builder = new InfoEditDialog.Builder(this);
builder.setTitle("填写信息")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String editText = builder.getFirstEditText();
Toast.makeText(MainActivity.this, editText, Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this, "点击了取消", Toast.LENGTH_SHORT).show();
}
})
.setFirstEditText("请输入您的银行卡号")
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
//关闭Dialog
builder.dismiss();
// 关闭当前 Activity
finish();
}
})
.show();
}
效果图:
4 最后写一下注意事项。
1.点击其他位置不会退出Dialog(点击左下角的回退三角会退出)
dialog.setCancelableTouchOutside(false)
2.点击所有位置都不会退出Dialog(点击左下角的回退三角也不会退出)
dialog.setCancelable(false);
3.取消dialog的同时将activity注销。
效果图:
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
//关闭Dialog
builder.dismiss();
// 关闭当前 Activity
finish();
}
})