翻译Dev Guide 之 创建Dialog

创建Dialog
一个Dialog通常是一个出现在目前Activity前方的小窗口。这个Dialog将接受用户的交互而底下的Activity将会失去焦点。Dialog通常用于需要打扰用户的通知,执行与应用程序进展直接相关的短暂任务(比如一个进度条或者登录提示)。
Dialog类是创建Dialog的基础类。但是,通常你不应该直接实例化Dialog类,而是使用以下子类之一:
 
  1.AlertDialog,可以管理0,1,2或者3个Button,和/或一个可以包含checkbox/radiobutton的可选项列表。AlertDialog可以构造大部分的DialogUI,并且是推荐的Dialog类型。
   2.ProgressDialog,展示了一个进度轮或者进度条,由于是AlertDialog的扩展,它也支持Button。
   3.DatePickerDialog,允许用户选择一个日期。
   4.TimePickerDialog,允许用户选择一个时间。
如果你希望定制自己的Dialog,你可以继承Dialog类或者以上的任意子类,然后重新定义布局。

显示一个Dialog

一个Dialog总是作为一个Activity的一部分来创建和显示。通常你应该在你的Activity的onCreateDialog(int)回调函数内创建Dialog。当你使用这个回调的时候,Android系统自动管理每个Dialog的状态并把它们挂到Activity,有效地让它成为每个Dialog的所有人。这样,每个Dialog从Acitivity继承了一些属性。比如,当一个Dialog打开的时候,Menu键会打开为这个Activity定义的optionsmenu,而Volume键会调整Activity使用的音频流。
注意:如果你决定在onCreateDialog()外创建一个Dialog,那么它对Acitivity不可见,但是你可以用setOwnerActivity(Activity)将它附着到Acitvity上。
当你想显示一个Dialog时,调用showDialog(int)并传递进一个唯一标识你想显示的Dialog的整数。
当一个Dialog第一次被请求时,Android从你的Activity调用onCreateDialog(int),在这个方法里你应该实例化你的Dialog。传入这个回调函数的ID跟传入showDialog(int)的是同一个。创建好Dialog后,在函数的末尾返回此对象。
在显示Dialog之前,Android还会调用可选的回调函数onPrepareDialog(int,Dialog)。如果你希望在每次打开Dialog的时候都修改它的属性,那么就定义这个函数。每次打开Dialog的时候这个函数会被调用,而onCreateDialog(int)只会在第一次打开Dialog的时候调用。如果你不定义onPrepareDialog(int,Dialog),那么Dialog将会和它上次打开时一样。Dialog的ID与你在onCreateDialog()里创建的Dialog将一起被传给这个函数。
调用showDialog(intid)时,会用id调用onCreateDialog(int)或者onPrepareDialog(int)进行创建或者修改,然后再显示出来。
//定义onCreateDialog(int)和onPrepareDialog(int, Dialog)的最佳方式,是用一个switch声明来检查传入的ID,每个case值检查一个唯一的Dialog ID,然后创建和定义各自的Dialog。比如,想象一个游戏使用了两个Dialog:一个说明游戏暂停,另一个说明游戏结束。首先,为每个Dialog定义一个整型ID:
    static final int DIALOG_PAUSED_ID = 0;
    static final int DIALOG_GAMEOVER_ID = 1;
//然后用一个包含了所有ID case的switch来定义onCreateDialog(int)回调:
    protected Dialog onCreateDialog(int id){
        Dialog dialog;
        switch (id) {
        case DIALOG_PAUSED_ID:
            // do the work to define the pause Dialog
            break;
        case DIALOG_PGAMEOVER_ID:
            // do the work to define the game over Dialog
            break;
        default:
            dialog = null;
        }
        return dialog;
    }
//要显示dialog的时候,用dialog的id调用showDialog(int):
    showDialog(DIALOG_PAUSED_ID);


解散一个Dialog

当你准备关闭你的dialog的时候,你可以调用Dialog对象的的dismiss()方法来解散它。必要的话,也可以从Activity上调用dismissDialog(int),它会为你有效地调用Dialog的dismiss()。
如果你用onCreateDialog(int)管理你的Dialog状态(如上节讨论),那么每次你的Dialog被解散的时候,Activity会保存它的状态。如果你决定你不再需要这个对象或者清理状态很重要,那么你需要调用removeDialog(int)。它会清除任何对此对象的内在关联,如果此dialog正在显示中的话,还会关闭它。
使用解散listener
如果你希望你的程序在解散Dialog的时候执行一些代码,那么你需要在你的dialog上附着on-dismisslistener。
首先定义DialogInterface.OnDismissListener接口。这个接口只有一个方法,onDismiss(DialogInterface),当dialog解散的时候会被调用。然后把你的OnDIsmissListener实现传递到setOnDismissListener()即可。
但是,注意Dialog也可以被cancel。这特指用户明确cancel这个dialog的情况。当用户按下back键来关闭dialog,或者Dialog显示调用cancel()(也许从dialog上的cancel按钮)时会发生。当一个dialog被cancel的时候,会通知OnDismissListener,但是如果你希望被告知dialog是显示调用cancel()而不是普通的dismiss,那么你需要注册一个DialogInterface.onCancelListener或者setOncancelListener()。


创建一个AlertDialog

AlertDialog是Dialog类的扩展,可以构造大部分的DialogUI,并且是推荐的Dialog类型。当dialog用到以下特性之一时你就应使用AlertDialg:
 
   一个title。
   一个文本消息。
   一个,两个或者三个Button。
   一个可选列表(包括可选的checkbox和radiobut)。
注意在AlertDialog文本消息和列表不能同时显示。
为了创建一个AlertDialog,使用AlertDialog.Builder子类。用AlertDialog.Builder(Context)获得一个Builder,然后使用这个类的公共方法定义AlertDialog的所有属性。完成后就可通过create()取回AlertDialog对象。
接下来的内容展示了如何用AlertDialog.Builder类来定义AlertDialog的各种属性。

添加Button

为了创建有side-by-side的Button的AlertDialog,使用set...Button()函数:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Are you sure you want to exit?")
                 .setCancelable(false)
                 .setPositiveButton("Yse", new DialogInterface.OnClickListener() {
                   
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        MyActivity.finish();
                       
                    }
                })
                .setNegativeButton("no", new DialogInterface.OnClickListener() {
                   
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                       
                    }
                });
        AlertDialog alert = builder.create();
首先用setMessage(CharSequence)为dialog添加一个message,然后开始函数链,用setCancelable(boolean)设置了dialog不能被cancel(用户不能用back键关闭dialog),为每个Button用一个set...Button(),接受Button的名字和DialogInterface.OnClickListener。
注意:每种Button只能添加一个,总共有三种为positive,neutral和negative。


添加一个列表

创建可选列表要用setItems()函数:
final CharSequence[] items = {"Red","Green","Blue"};
       
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Pick a color");
        builder.setItems(items, new DialogInterface.OnClickListener() {
           
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(getApplicationContext(), items[which], Toast.LENGTH_SHORT).show();
            }
        });
        AlertDialog alert = builder.create();
首先,用setTitle(CharSequence)给Dialog设置一个标题,然后用setItem()添加一个可选列表,它接收一个选项数组用于显示和一个DialogInterface.OnClickListener用于监听点击选项。


添加checkbox和radiobutton

向Dialog里添加一个有复选选项checkbox或者单选选项radiobutton的列表,各自要用setMultiChoiceItems()和setSingleChoiceItems()函数。如果你在onCreateDialog()回调函数里使用了这些,Android会替你管理列表的状态。只要Activity还活跃,dialog就会记住上次选择的选项,但是如果用户退出Activity,选择就忘记了。
注意:为了在用户离开或者暂停Activity时保存选择,你必须在整个Activity生命周期中进行恰当的存储和恢复。为了永久地保存选择,即使Activity的进程完全停止,你需要使用一种数据存储技术(DataStorage)。
要创建一个选项可单选列表,代码和上面一样,只需要把setItems()换成setSingleChoiceItems()。
final CharSequence[] items = {"Red","Green","Blue"};
       
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Pick a color");
        builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
           
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(getApplicationContext(), items[which], Toast.LENGTH_SHORT).show();
            }
        });
        AlertDialog alert = builder.create();
setSingleChoiceItems()中第二个参数是标记选项的一个整数,说明了这个零基列表默认的选项位置,选择“-1”表示默认无选项被选中。


创建ProgressDialog

ProgressDialog是Dialog的扩展,可以为一个有未定义进度的任务以一个旋转的轮子形式显示进度动画,或者为一个有已定义进度的任务显示进度条,还可以提供按钮用于比如退出一个下载。
打开一个ProgressDialog只要调用ProgressDialog.show()就可以了。比如:
    ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "", "Loading, Please wait...", true);
第一个参数是应用程序的context,第二个是dialog的标题,第三个是message,第四个表示进度是否不定(只跟进度条有关,下节讨论)。
默认的ProgressDialog类型就是旋转的轮子,如果你想要创建按粒度显示进度的进度条,需要更多代码如下。

显示进度条



用动态进度条显示进度的步骤:
   1.用类构造器ProgressDialog(Context)初始化ProgessDialog。
   2.用setProgressStyle(int)把进度类型设置为“STYLE_HORIZONTAL”,并设置其他属性,如message等。
   3.当你准备显示Dialog时,调用show(),或者返回来自onCreateDialog(int)回调的ProgressDialog。
   4.你可以用目前完成的百分比调用setProgress(int),或者用加到目前完成百分比的增量值调用incrementProgressBy(int),来增加显示在进度条上的进度量。
注意设置进度一定要在show()之后,否则设置无效。
比如你的设置可以是这样:
ProgressDialog progressDialog = new ProgressDialog(mContext);
    progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    progressDialog.setMessage("Loading...");
    progressDialog.setCancelable(false);

设置很简单。创建一个ProgressDialog的大部分代码实际上都包含在更新程序中了。你也许会发现有必要在应用程序中创建一个次线程去完成这个工作,然后有一个Handler对象把进度回报给Activity的UI线程。


创建自定义Dialog

如果你想自主设计一个Dialog,你可以用layout和widget元素为Dialog窗口创建一个你自己的布局。定义完布局之后,把根View对象或者布局资源ID传给setContentView(View)。步骤:
   1.创建XML布局文件,如custom_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

                
      android:id="@+id/layout_root"

                 
      android:orientation="horizontal"

                 
      android:layout_width="fill_parent"

                      
android:layout_height="fill_parent"

                      
android:padding="10dp"

                      >
        
        
<ImageView android:id="@+id/image"

                      android:layout_width="wrap_content"

                 
      android:layout_height="fill_parent"

                 
      android:layout_marginRight="10dp"

                />

               <TextView android:id="@+id/text"

                      
android:layout_width="wrap_content"

                    
  android:layout_height="fill_parent"

                      
 android:textColor="#FFF"

               />
        
</LinearLayout>

这个XML在一个LinearLayout里定义了一个ImageView和一个TextView。

    2.把上面的布局设置为dialog的内容布局,定义ImageView和TextView的内容。

Context mContext = getApplicationContext();
        
Dialog dialog = new Dialog(mContext);


        
dialog.setContentView(R.layout.custom_dialog);
        
dialog.setTitle("Custom Dialog");


        
TextView text = (TextView) dialog.findViewById(R.id.text);
        
text.setText("Hello, this is a custom dialog!");
        
ImageView image = (ImageView) dialog.findViewById(R.id.image);
        
image.setImageResource(R.drawable.android);

在你实例化Dialog后,将layout资源ID传给setContentView(int)把你自己的layout设为dialog的内容视图,然后Dialog有了一个已定义的布局,可以用findViewById(int)来捕捉View对象并修改其内容了。

注意,经过测试发现,按如上代码直接对自定义Dialog使用findViewById()是不能获取控件的,正确的做法是:
    先获取LayoutInflater,用其inflate(int, ViewGroup)方法对自定义布局进行缩放,得到一个View。
    然后用自己的Dialog的setContentView(View)将这个View设置为Dialog的布局。
    在通过这个View的对象名来调用findViewById()来获取控件。 但是设置布局文件和设置其控件并无严格的顺序,为了便于记忆和理解,尽量先设置布局文件,在设置其控件。     3.搞定。现在你可以显示你的Dialog了。 一个用Dialog基础类做的Dialog必须有个标题。如果你不调用setTitle(),那标题位置就是空的,但仍然可见。如果你根本不想要标题,那么你应该用AlertDialog类创建自己的Dialog。但是,由于AlertDialog用AlertDialog.Builder创建是最简单的,你接触不到上面用的setContentView(View),而必须用setView(View)。这个函数接受一个View对象,所以你需要膨胀布局XML的根View对象。 要膨胀XML布局,用getLayoutInflater()或者getSystemService()获取LayoutInflater,然后调用inflate(int, ViewGroup),第一个参数是布局资源ID,第二个是根View的ID。然后你就可以被膨胀的layout去发现View对象及设置它们的属性了。然后实例化AlertDialog.Builder,并用setView()把被膨胀了的layout设置到Dialog中。 下面有个在AlertDialog中创建自定义Dialog的示例:
AlertDialog.Builder builder;

        AlertDialog alertDialog;

        

        Context mContext = getApplicationContext();

        LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(LAYOUT_INFLATER_SERVICE);

        View layout = inflater.inflate(R.id.custom_dialog, 

                        (ViewGroup)layout.findViewById(R.id.layout_root));

        

        TextView text = (TextView)findViewById(R.id.text);

//同样的,这里获取TextView应该用(TextView)layout.findViewById(R.id.text);

        text.setText("Hello, this is a custom dialog!");

        ImageView image = (ImageView)findViewById(R.id.image);

        image.setImageResource(R.drawable.android);

        

        builder = new AlertDialog.Builder(mContext);

        builder.setView(layout);

        alertDialog = builder.create();

为你的布局使用AlertDialog可以利用AlertDialog的内在特性,比如被管理的按钮,可选列表,标题,图标等等。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章