对话框在任何开发中都十分常用,Android中的对话框功能更是全面有强大。App的使用一定程度上依赖于用户交互,良好的体验就要从完善的提示功能开始。
Dialog作为警告对话框,在退出或删除时最为常用。在Android中对话框中可以显示文字、按钮、单选多选按钮、进度条、日期时间选择器甚至一个列表项乃至一个界面。
对话框主要有四个区域:图标区、标题区、内容区、按钮区,不同的区域都有特定的方法去设置。
Dialog作为一种控件并不能通过布局文件创建,任何时候它都需要事件触发的,所以只能在Java代码中创建和使用。对话框中使用最多的是AlertDialog,虽然使用繁复,需要设置的内容很多,但正是因为它的每个部分都可以自定义才会如此强大和广泛应用。要想创建对话框需要创建AlertDialog.Builder对象,它是AlertDialog的内部类,专门用于设置对话框的四个区域。
主要方法如下
AlertDialog.Builder.setTitle()或setCustomTitle()设置对话框的标题
AlertDialog.Builder.setIcon()设置对话框的图标
AlertDialog.Builder显示内容方法:
setMessage()设置文本提示信息
setSingleChoiceItems()设置内容为单选按钮,参数有选项的数组,默认选项id,选择监听器
setMultiChoiceItems()设置内容为多选按钮,参数有选项的数组,默认各选项是否选中(一个布尔类型数组表示,每个选项必须都设定),选择监听器
setItems()设置内容为简单列表项,参数有列表项数组(ListView)
setAdapter()设置内容为自定义列表项(ListView)
setView()设置内容为任意类型View(可以是一个布局)
AlertDialog.Builder设置按钮的方法:
setPositiveButton()
setNegativeButton()
setNeutralButton()//三个方法用法相同,设置几个就显示几个按钮,至于各个按钮并不代表特定功能的按钮
AlertDialog.Builder.create()创建AlertDialog对象
AlertDialog对象show()方法显示对话框
这样,对话框创建好了,其中其他方法在下面的实例中标注介绍。
DatePickerDialog、TimePikerDialog、ProgressDialog三种Dialog的使用很相似,Android为它们定制了专属的创建方法,不需要通过AlertBuilder类创建,直接通过自己的Dialog方法创建完成使用show()方法显示即可,使它们的使用更为简单。DatePickerDialog和TimePickerDialog中包含一个名为“完成”的按钮,可以通过监听事件获取选择的时间。
以下以一个注册界面为例简单测试一下这些Dialog,从上到下依次是包含普通文本的对话框、包含单选按钮的对话框、包含多选按钮的对话框、包含自定义View的对话框、日期选择对话框、时间选择对话框及进度条对话框。
设置模式是这样的:以按钮触发对话框,通过对话框来选择和填入信息,通过监听器获取选择的信息填到按钮上。
要使用这么多的按钮,且格式都一样,所以这里通过values中的styles文件来为它们设置相同的格式。首先为它们写出不同不同状态的shape文件,然后将shape引用到selector文件,最后将selector文件以backgroud属性引用到styles文件中,并设置其他相同属性,最终通过style属性引用styles文件为Button设置的样式就达到目的了。
按钮未点击的shape文件:off_shape.xml
Dialog作为警告对话框,在退出或删除时最为常用。在Android中对话框中可以显示文字、按钮、单选多选按钮、进度条、日期时间选择器甚至一个列表项乃至一个界面。
对话框主要有四个区域:图标区、标题区、内容区、按钮区,不同的区域都有特定的方法去设置。
Dialog作为一种控件并不能通过布局文件创建,任何时候它都需要事件触发的,所以只能在Java代码中创建和使用。对话框中使用最多的是AlertDialog,虽然使用繁复,需要设置的内容很多,但正是因为它的每个部分都可以自定义才会如此强大和广泛应用。要想创建对话框需要创建AlertDialog.Builder对象,它是AlertDialog的内部类,专门用于设置对话框的四个区域。
主要方法如下
AlertDialog.Builder.setTitle()或setCustomTitle()设置对话框的标题
AlertDialog.Builder.setIcon()设置对话框的图标
AlertDialog.Builder显示内容方法:
setMessage()设置文本提示信息
setSingleChoiceItems()设置内容为单选按钮,参数有选项的数组,默认选项id,选择监听器
setMultiChoiceItems()设置内容为多选按钮,参数有选项的数组,默认各选项是否选中(一个布尔类型数组表示,每个选项必须都设定),选择监听器
setItems()设置内容为简单列表项,参数有列表项数组(ListView)
setAdapter()设置内容为自定义列表项(ListView)
setView()设置内容为任意类型View(可以是一个布局)
AlertDialog.Builder设置按钮的方法:
setPositiveButton()
setNegativeButton()
setNeutralButton()//三个方法用法相同,设置几个就显示几个按钮,至于各个按钮并不代表特定功能的按钮
AlertDialog.Builder.create()创建AlertDialog对象
AlertDialog对象show()方法显示对话框
这样,对话框创建好了,其中其他方法在下面的实例中标注介绍。
DatePickerDialog、TimePikerDialog、ProgressDialog三种Dialog的使用很相似,Android为它们定制了专属的创建方法,不需要通过AlertBuilder类创建,直接通过自己的Dialog方法创建完成使用show()方法显示即可,使它们的使用更为简单。DatePickerDialog和TimePickerDialog中包含一个名为“完成”的按钮,可以通过监听事件获取选择的时间。
以下以一个注册界面为例简单测试一下这些Dialog,从上到下依次是包含普通文本的对话框、包含单选按钮的对话框、包含多选按钮的对话框、包含自定义View的对话框、日期选择对话框、时间选择对话框及进度条对话框。
设置模式是这样的:以按钮触发对话框,通过对话框来选择和填入信息,通过监听器获取选择的信息填到按钮上。
要使用这么多的按钮,且格式都一样,所以这里通过values中的styles文件来为它们设置相同的格式。首先为它们写出不同不同状态的shape文件,然后将shape引用到selector文件,最后将selector文件以backgroud属性引用到styles文件中,并设置其他相同属性,最终通过style属性引用styles文件为Button设置的样式就达到目的了。
按钮未点击的shape文件:off_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="10dp"/>
<stroke android:width="2dp"
android:color="#00ff00"/>
<padding android:left="10dp"
android:right="10dp"
android:top="5dp"
android:bottom="5dp"/>
</shape>
按钮被点击的shape文件:on_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="10dp"/>
<stroke android:width="2dp"
android:color="#ffffff"/>
<padding android:left="10dp"
android:right="10dp"
android:top="5dp"
android:bottom="5dp"/>
</shape>
按钮selector文件:btn_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true"
android:drawable="@drawable/on_shape"></item>
<item android:state_pressed="false"
android:drawable="@drawable/off_shape"></item>
</selector>
styles.xml文件如下
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
<style name="button">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">@drawable/btn_selector</item>
<item name="android:layout_marginTop">10dp</item>
<item name="android:textColor">#00ff00</item>
</style>
</resources>
布局文件如下
<LinearLayout 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="#000000"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.briup.alertdialog.MainActivity" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/d81"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="用户注册"
android:textSize="20sp"
android:textColor="#ff0000"
android:padding="15dp"
android:gravity="center"/>
<Button
style="@style/button"
android:onClick="btn1"
android:text="退出用户注册" />
<Button
style="@style/button"
android:onClick="btn2"
android:text="性别" />
<Button
style="@style/button"
android:onClick="btn22"
android:text="爱好" />
<Button
style="@style/button"
android:onClick="btn3"
android:text="用户名和密码" />
<Button
style="@style/button"
android:onClick="btn4"
android:text="生日" />
<Button
style="@style/button"
android:onClick="btn5"
android:text="起床时间" />
<Button
style="@style/button"
android:onClick="btn6"
android:text="保存" />
</LinearLayout>
自定义布局文件litle_view.xml如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="#00ff00"
android:gravity="center"
android:text="设置用户名和密码"
android:textColor="#000000"
android:textSize="20sp" />
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入名字" />
<EditText
android:id="@+id/pass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码"
android:password="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/queding"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="确定" />
<Button
android:id="@+id/quxiao"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="取消" />
</LinearLayout>
</LinearLayout>
MainActivity.class类文件如下
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.ProgressDialog;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TimePicker;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
public void btn1(View v){
AlertDialog.Builder builder = new Builder(this);
builder.setIcon(R.drawable.ic_launcher);//设置图标
builder.setTitle("AlertDialog");//设置标题
builder.setMessage("是否确定退出?");//设置简单的内容
builder.setPositiveButton("确定", new OnClickListener() {
//确定按钮(文字及监听器)
@Override
public void onClick(DialogInterface dialog, int which) {
MainActivity.this.finish();//退出当前Activity
}
});
builder.setNegativeButton("取消", new OnClickListener() {
//亦可以简单写为builder.setNegativeButton("取消", null),默认调用dismiss()
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();//取消对话框方法
}
});//取消按钮,二者除了名字基本无区别,NegativaButton会在前面
builder.setCancelable(false);//设置是否可以除点击按钮外取消对话框(需要在create方法前调用)(false情况下即使点击返回也不能取消,true点击以外区域及返回键均可)
builder.create();//创建AlertDailog对象
builder.show();//显示对话框
}
@Override
//点击手机物理按钮
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK){//通过静态常量找到返回键
AlertDialog.Builder builder = new Builder(this);
builder.setIcon(R.drawable.ic_launcher);//设置图标
builder.setTitle("AlertDialog");//设置标题
builder.setMessage("是否退出?");//设置简单的内容
builder.setPositiveButton("确定", new OnClickListener() {
//确定按钮(文字及监听器)
@Override
public void onClick(DialogInterface dialog, int which) {
MainActivity.this.finish();//退出
}
});
builder.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();//取消对话框方法
}
});
builder.setCancelable(false);
builder.create().show();
}
return true;
}
public void btn2(View view){
final Button btn2 = (Button) view;//拿到当前按钮,为方便调用设置为final
final String[] sex = {"男","女"};
AlertDialog.Builder builder = new Builder(this);
builder.setIcon(R.drawable.ic_launcher);
builder.setTitle("请选择性别");
builder.setSingleChoiceItems(sex,//选项预设
0, //默认选择
new OnClickListener() {
//这种Dialog我们可以不用Button
@Override
public void onClick(DialogInterface dialog, int which) {
btn2.setText(sex[which]);//which表示第几个(从0开始)
dialog.dismiss();
}
});
builder.create().show();
}
public void btn22(View view){
final Button btn22 = (Button) view;
final String[] like = {" Java "," Oracle "," JDBC "," Android "};//备选项
final List<String> list = new ArrayList<String>();//用于存放选择的内容
AlertDialog.Builder builder = new Builder(this);
builder.setIcon(R.drawable.ic_launcher).setTitle("请选择爱好");
builder.setMultiChoiceItems(like,
new boolean[] {false,false,false,false},//设定多选按钮是否选中
new OnMultiChoiceClickListener() {
//选择监听器
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
Toast.makeText(MainActivity.this, isChecked?"选中"+like[which]:"取消"+like[which], Toast.LENGTH_SHORT).show();
if(isChecked)
list.add(like[which]);
}
});
builder.setPositiveButton("确定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String str="";
for(String s:list)
str += s;//不提倡这种方式来叠加字符串,消耗内存极大
if(!str.trim().equals(""))
btn22.setText(str);
}
});
builder.create().show();
}
public void btn3(View view){
final Button btn3 = (Button) view;
AlertDialog.Builder builder = new Builder(this);
View v = View.inflate(this, R.layout.litle_view, null);//获取布局
Button btn_queding = (Button) v.findViewById(R.id.queding);//获取控件
Button btn_quxiao = (Button) v.findViewById(R.id.quxiao);
final EditText name = (EditText) v.findViewById(R.id.name);
final EditText pass = (EditText) v.findViewById(R.id.pass);
builder.setView(v);//设置View进Builder
final AlertDialog dialog = builder.create();
dialog.show();
btn_queding.setOnClickListener(new android.view.View.OnClickListener() {
//为控件添加监听,为什么要使用完整包名+类名:同一篇代码引用不同包相同名的类需要使用全名
@Override
public void onClick(View v) {
if(name.getText().toString().equals("")&&pass.getText().toString().equals(""))
Toast.makeText(MainActivity.this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
else{
btn3.setText(name.getText().toString());
dialog.cancel();//取消dialog,与dismiss方法效果相同
}
}
});
btn_quxiao.setOnClickListener(new android.view.View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.cancel();
}
});
}
public void btn4(View view){
final Button btn4 = (Button) view;
Calendar calendar = Calendar.getInstance();//通过日历获取系统日期(手机的时间)
int year = calendar.get(Calendar.YEAR);//拿到年
int month = calendar.get(Calendar.MONTH);//拿到月
int day = calendar.get(Calendar.DAY_OF_MONTH);//拿到天
DatePickerDialog date = new DatePickerDialog(this, new OnDateSetListener() {
//这种Dialog只有一个按钮,名字叫“完成”
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
//这里拿到的月数需要加1,因为每年的月份是从0-11
btn4.setText( year+"-"+(month+1)+"-"+dayOfMonth);
}
}, year, month, day);//年月日的格式跟随手机设置(年-月-日或月-日-年)
date.show();//直接使用类创建,所以不需要通过create创建
}
public void btn5(View view){
final Button btn5 = (Button) view;
Calendar calendar = Calendar.getInstance();//通过日历获取系统日期
int hour = calendar.get(Calendar.HOUR_OF_DAY);//拿到小时
int minute = calendar.get(Calendar.MINUTE);//拿到分钟
TimePickerDialog time = new TimePickerDialog(this, new OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
btn5.setText( hourOfDay+":"+minute);
}
}, hour, minute, true);//最后一个参数表示是否显示为24小时制,false:12小时制,前面多一个按钮选择上下午,true:24小时制,没有前面的按钮
time.show();
}
//要使用进度条就要使用线程,我们这里不对进度条的关闭添加逻辑
public void btn6(View view){
ProgressDialog progress = new ProgressDialog(this);
progress.setIcon(R.drawable.ic_launcher);
progress.setTitle("正在保存");
progress.setMessage("Loading...");//设置文字,显示在圆形进度条的右边,水平进度条的上面
//progress.setIndeterminate(true);//设置水平进度条为持续流动方式,没有进度比例,该模式下setMax()等方法亦无效
//progress.setMax(100);//设置水平进度条最大值
//progress.setProgress(0);//设置水平进度条当前进度
//progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//水平进度条
//progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);//默认值,圆形的进度条,如果什么都不设置,setMax()等方法失效
progress.show();
}
}
效果如下