Android之Dialog分析
以Dialog为引导,Android的弹出式消息一共是三种(据我所知):Dialog,tocast,notification 其三种弹出式消息各有所长。今天重点是分析其中的Dialog。Android的Dialog是android界面编程的重点。当然android被称之为“页程序”就更体现页面编程,UI线程了解的重要性了。
本文的目录结构:
1、Android中的几种Dialog
2、Dialog的创建方式
3、Android的警告对话框AlertDialog
4、Android的进度框ProgressDialog
5、日期选择框& 时间选择框
6、对话框风格的窗口
7、popupwindow
创建对话框一般是出现在当前Activity之上的一个小窗口,此时Activity失去焦点,转由对话框接受用户的交互(触摸响应事件)
首先看一看Dialog的类图,由此可以更清晰的看到控件的属性继承关系
一、Android中的几种Dialog:
1、 自定义:Dialog
2、 警告框:AlertDialog
3、 进度框:ProgressDialog
4、 日期选择框:DatePickerDialog
5、 时间选择框:TimePickerDialog
Android的其他几种类似的窗口
1、 对话框风格的窗口
2、 Popupwindow
二、Dialog的创建方式总的来说是两种:
1、 直接new一个Dialog对象,然后调用Dialog对象的show()和dismiss()方法来控制对话框的显示和隐藏
2、 在Activity的onCreateDialog(intid)方法中创建Dialog对象并返回,然后调用Activity的showDialog(int id)和dismissDialog(int id)来显示和隐藏对话框
这两者的区别在于通过第二种方式创建的对话框会继承Activity的属性,并且Android系统会自动管理每个对话框的状态并将它们和Activity连接,这样当打开一个对话框时,Menu键会显示Activity的菜单,音量键会调整Activity当前使用的音频流的音量。同时第二种方式在Activity中有父类方法可实现:
onPrepareDialog(int, Dialog):如果希望每次显示对话框的时候有动态更改的内容,那么修改这个函数
onCreateDialog(int)当一个对话框第一次被请求时,Android调用这个方法,这是初始化对话框的地方,创建对话框之后,将返回被创建的对象
dismissDialog(int)二者的效果是一样的。
removeDialog(int)如果你使用onCreateDialog(int)来管理你的对话框的状态, 那么每次你的对话框被解除时, 该对话框对象的状态会被Activity保存. 如果你决定你不再需要这个对象或者需要清除对话框的状态, 那么你应该调用这个方法。这将把所有该对象的内部引用移除。
三、Android的警告对话框AlertDialog
其实警告对话框AlertDialog是作为Dialog的一个拓展,方便与应用各种固定模式的对话框中;确定的生成对话框,包括标题,内容,选项,按钮等的设置和响应等;这很方便,但是实际实现中却也有自己的短板:theme改变不了(貌似是固定的,比如想设置Dialog的背景色透明就不行,可能我还不会用全)。
下面介绍AlertDialog的基本用法:
AlertDialog生成的对话框可分为如下四个区域:
·生成对象 使用创建 AlertDialog.Builder对象
·图标区 调用AlertDialog.Builder的setIcon方法设置
·标题区 调用AlertDialog.Builder的setTitle()或setCustomTitle()方法设置标题
·内容区 调用AlertDialog.Builder的相关设置方法设置对话框内容
·按钮区 调用AlertDialog.Builder的setPositiveButton()、setNegativeButton() 或setNeutralButton()方法添加多个按钮。
调用AlterDialog.Builder的create()方法创建AlertDialog对象,再调用AlertDialog对象的show方法将该对话框显示出来。
以上的是AlertDialog的固定模式;
具体更改内容区的显示内容可达到不同的目的,AlertDialog提供如下六中方法来指定对话框的内容。
setMessage():设置对话框内容为简单的文本内容
setItems():设置对话框内容为简单列表项
setSingleChoiceItems():设置对话框内容为单选列表项
setMultiChoiceItems():设置对话框内容为多选列表项
setAdapter():设置对话框内容为自定义列表项
setView():设置对话框内容为自定义的View
以上的这六种对话框基本就是可以满足需要了,详细的实现可参考博文:http://www.oschina.net/question/54100_32486
四,Android的进度框ProgressDialog
一个ProgressDialog(进度对话框)是AlertDialog的扩展。它可以显示一个进度的动画——进度环或者进度条。这个对话框也可以提供按钮,例如取消一个下载等。
进度框Dialog是一个明显的直接面对进度框的Dialog,这样做是免除了自定义progress 的Dialog或是AlertDialog的复杂。
其具体实现有两种方式:
1、只是创建简单的进度对话框,调用ProgressDialog提供的静态show()方法显示对话框即可
2、是new ProgressDailog(this)获取对象,然后设置属性等
五、日期选择框 & 时间选择框
日期选择框(DatePickDialog)和时间选择框(TimePickerDialog)的使用是比较简单的,两个步骤:
1、 都是先new出DatePickDialog & TimePickerDialog实例,调用其show()方法即可显示出来。
2、 为其绑定监听器;设置事件监听器,从而获取用户设置的事件(时间& 日期)
在new出对象的同时,监听器是必须的
NewDtePickerDialog(this, new DatePickerDialog.OnDateSerListener(){…在实现方法中获取日期…});
NewTimerPickerDialog(this, new TimePcikerDialog.OnTimeSetListener(){…在实现方法中获取时间…});
六、对话框风格的窗口
其实本质上仍然是窗口,并不能算是Dialog;其本质上是Activity,只是将它做成了对话框风格而已。
这个是在Activity中配置相关theme主题就ok了。
<activity
android:name=".ServerConfigDialogActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Dialog">
<intent-filter>
<action
android:name="android.intent.action.MAIN"/>
<category
android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
七、popupwindow
Popupwindow也是可以创建类似对话框风格的窗口的,使用简单,两个步骤:
1、 popupwindow的构造器创建popupwindow对象
2、 显示的方式有两种:
1、 作为某控件的下拉项:showAsDropDown(View v)
2、 指定位置展示:showAtLocation()在指定位置显示出来
(示例中的重点是点击外部事件的时候popupwindow会不会消失的问题,设置背景很重要)
packagecom.example.hellopopupwindow;
importandroid.os.Bundle;
importandroid.app.Activity;
importandroid.content.Context;
importandroid.util.Log;
importandroid.view.LayoutInflater;
importandroid.view.MotionEvent;
importandroid.view.View;
import android.view.View.OnClickListener;
importandroid.view.View.OnTouchListener;
importandroid.view.ViewGroup.LayoutParams;
importandroid.widget.Button;
importandroid.widget.PopupWindow;
importandroid.widget.Toast;
public classMainActivity extends Activity {
private Context mContext = null;
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(newView.OnClickListener() {
@Override
public void onClick(View view) {
showPopupWindow(view);
}
});
}
private void showPopupWindow(View view) {
// 一个自定义的布局,作为显示的内容
View contentView =LayoutInflater.from(mContext).inflate(
R.layout.pop_window, null);
// 设置按钮的点击事件
Button button = (Button) contentView.findViewById(R.id.button1);
button.setOnClickListener(newOnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext,"button is pressed",
Toast.LENGTH_SHORT).show();
}
});
final PopupWindow popupWindow = newPopupWindow(contentView,
LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, true);
popupWindow.setTouchable(true);
popupWindow.setTouchInterceptor(newOnTouchListener() {
@Override
public boolean onTouch(View v,MotionEvent event) {
Log.i("mengdd","onTouch : ");
return false;
// 这里如果返回true的话,touch事件将被拦截
// 拦截后 PopupWindow的onTouchEvent不被调用,这样点击外部区域无法dismiss
}
});
// 如果不设置PopupWindow的背景,无论是点击外部区域还是Back键都无法dismiss弹框
// 我觉得这里是API的一个bug
popupWindow.setBackgroundDrawable(getResources().getDrawable(
R.drawable.selectmenu_bg_downward));
// 设置好参数之后再show
popupWindow.showAsDropDown(view);
}
}