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 会用 android 系统dialog_android 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

以上的这六种对话框基本就是可以满足需要了,详细的实现可参考博文:


四,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);
    }
}