【翻译文档】Android Dialog

 声明:本文翻译自Android SDK自带文档中的guide/topics/ui/dialogs.html

  一个dialog通常是指出现在当前Activity前面的小窗口,当dialog出现后,被它部分遮盖的Activity将失去焦点,一切的用户操作交由这个dialog处理。

  Android API支持以下类型的Dialog对象:

  AlertDialog -- 允许你在其上添加0、1、2或3个button,而且它还可以包含一个提供了可选项(如checkboxes或radio buttons等)的列表。正确的使用AlertDialog可以构建大多数Dialog界面。

  ProgressDialog -- 用于显示一个progress wheel或者一个progress bar。ProgressDialog是一个别扩展了的AlertDialog,所以它自然也允许你在其上添加button。

  DatePickerDialog -- 允许用户选择时间的dialog。

  TimePickerDialog -- 允许用户选择时间的dialog。

  如何显示一个Dialog

  一个dialog常常作为一个Activity的一部分被创建和显示。你应该在你创建的Activity的 onCreateDialog(int)这个回调函数中创建dialog。当你使用这个回调函数,Android系统就会自动管理每个dialog的状态并且创建每个dialog和对应Activity之间的连接,使对应的Activity成为对应dialog的“owner”。这样,每个dialog就从Activity继承了某些属性。例如,当一个dialog处于open状态时,用户按下Menu键就会显示你为这个Activity定义的menu。

  注意:如果你决定在onCreateDialog()外面创建一个dialog,Android系统不会把它“粘贴” 到某个Activity上。如果需要,你可以使用setOwnerActivity(Activity)方法将一个dialog“粘贴”到一个 Activity上。

  当你想要显示一个dialog时,请调用showDialog(int)方法,并且传递给它一个能唯一标识你想要显示的dialog的整数。

  当一个dialog第一次被请求的时候,Android系统会呼叫你的Activity中的 onCreateDialog(int)方法,你要在这个方法体里实例化一个Dialog。onCreateDialog和showDialog一样,都需要你传递给它们一个dialog ID。在你创建完一个Dialog对象后,请让onCreateDialog方法返回一个Dialog对象的引用。

  在dialog被显示之前,Android也会呼叫onPrepareDialog(int, Dialog)。这个方法是可选的,如果你想在每次打开dialog时改变它任何树形,你就需要定义这个方法。每次dialog别打开时,Android 都会呼叫onPrepareDialog(int, Dialog),而只有当dialog是被第一次打开时才呼叫onCreateDialog(int)。如果你比重写

  

onPrepareDialog(int, Dialog),dialog就会呈现用户上一次打开它时的状态。这个方法也需要你传递给它一个dialog的ID,同时还需要你传递给它一个你使用 onCreateDialog()方法创建并返回的Dialog对象的引用。

  最好的定义 onCreateDialog(int)和onPrepareDialog(int, Dialog) 这两个回调函数的方法是使用switch语句检测被传入的id实参。每个case应该检测一个惟一的dialog ID,然后创建和定义各自的Dialog对象。例如,假设需要两个不同对话框的一个游戏程序,一个对话框指示这个游戏已被暂停,两一个指示游戏结束。

  首先,为每个dialog定义一个ID:

  view plaincopy to clipboardprint?

  static final int DIALOG_PAUSE_ID = 0;

  static final int DIALOG_GAMEOVER_ID = 1;

  static final int DIALOG_PAUSE_ID = 0;

  static final int DIALOG_GAMEOVER_ID = 1;

  然后,定义onCreateDialog(int)方法,其中应该包含用于区别不同dialog ID的switch语句:

  view plaincopy to clipboardprint?

  protected Dialog onCreateDialog(int id)

  {

  Dialog dialog;

  switch (id)

  {

  case DIALOG_PAUSE_ID:

  // do the work to define the pause Dialog

  break;

  case DIALOG_GAMEOVER_ID:

  // do the work to define the game over Dialog

  break;

  default:

  dialog = null;

  }

  return dialog;

  }

  protected Dialog onCreateDialog(int id)

  {

  Dialog dialog;

  switch (id)

  {

  case DIALOG_PAUSE_ID:

  // do the work to define the pause Dialog

  break;

  case DIALOG_GAMEOVER_ID:

  // do the work to define the game over Dialog

  break;

  default:

  dialog = null;

  }

  return dialog;

  }

  注意:在以上例子中,在case分支语句中并没有代码,因为本节还没有讲述定义Dialog的处理过程。

  接下来,是时候去显示一个dialog了,请调用showDialog(int),并传递给它一个dialog的ID。

  

  view plaincopy to clipboardprint?

  showDialog(DIALOG_PAUSED_ID);

  showDialog(DIALOG_PAUSED_ID);

  如何让一个Dialog消失

  当你打算关闭一个dialog,可以调用Dialog对象成员方法dismiss()方法来打发它。如果有必要,你可以从为你呼叫dismiss()的Activity中调用dismisDialog(int)。

  如果你正在使用onCreateDialog(int)去管理dialog的状态,那每次你的dialog消失后,Activity就持有Dialog对象的状态信息。如果你真的不再需要这个Dialog对象,或者你真的需要清除这个状态,那你应该呼叫 removeDialog(int)。这个方法会擦除所有与这个对象相关的内部引用,并且如果dialog正在被显示,这个方法会dismiss这个 dialog。

  如何使用dismiss监听器

  如果你想让你的应用程序在dialog消失的过程中做一些事,你就应该为你的Dialog绑定一个on-dismiss监听器。

  首先,定义DialogInterface.OnDismissListener接口。这个接口只有一个方法—— onDismiss(DialogInterface),在dialog消失后,系统就会呼叫这个方法。然后把你的实现了 OnDismissListener接口的对象传递给setOnDismissListener()。

  然后,值得注意的是dialog也能够够取消(be cancelled)。这是一种标识dialog被用户显示取消的特殊情况。当用户按下了返回键或者关闭了这个dialog或者应用程序员显示的调用了 cannel()时(可能在dialog中的“Cancel”按钮被按下的处理方法中调用的),就会发生这种情况。当一个dialog处在被取消的状态,OnDismissListener也会接收到来自Android的通知,但如果你想Android在这个dialog被显示取消(and not dismissed normally),就得使用setOnCancelListener()方法注册一个 DialogInterface.OnCancelListener。

  如何创建一个AlertDialog

  AlertDialog是Dialog类的扩展类,它可以构建很多中dialog用户界面,Android也建议应用程序员使用AlertDialog完成dialog用户界面的构建。你可以用它构建具有任何一下属性的dialog:

  A title

  A text message

  One, two, or three buttons

  A list of selectable items(with optional checkboxes or radio buttons)

  为了创建一个AlertDialog,你需要使用AlertDialog.Builder子类。使用 AlertDialog.Builder(Context)获得一个Builder,然后使用类的公开方法去定义AlertDialog的所有属性。在你已经完成了对Builder的操作后,呼叫create()方法取回这个AlertDialog对象。

  

  以下内容论述和展示了如何使用AlertDialog.Builder类,定义AlertDialog的各种属性。如果你在onCreateDialog()回调函数中使用下面任何一段代码,你就可以返回你想要显示的具有某些属性的目标Dialog对象。

  添加button

  如果你想构建一个带有button的dialog,需要调用set...Button()方法。

  view plaincopy to clipboardprint?

  AlertDialog.Builder builder = new AlertDialog.Builder(this);

  builder.setMessage("Are you sure you want to exit?")

  .setCancelable(false)

  .setPositiveButton("Yes", new DialogInterface.OnClickListener() {

  public void onClick(DialogInterface dialog, int id) {

  MyActivity.this.finish();

  }

  })

  .setNegativeButton("No", new DialogInterface.OnClickListener() {

  public void onClick(DialogInterface dialog, int id) {

  dialog.cancel();

  }

  });

  AlertDialog alert = builder.create();

  AlertDialog.Builder builder = new AlertDialog.Builder(this);

  builder.setMessage("Are you sure you want to exit?")

  .setCancelable(false)

  .setPositiveButton("Yes", new DialogInterface.OnClickListener() {

  public void onClick(DialogInterface dialog, int id) {

  MyActivity.this.finish();

  }

  })

  .setNegativeButton("No", new DialogInterface.OnClickListener() {

  public void onClick(DialogInterface dialog, int id) {

  dialog.cancel();

  }

  });

  AlertDialog alert = builder.create();

  首先,呼叫setMessage(CharSequence)为dialog添加一条提示消息。然后,开始 method-chaining并且呼叫setCancelable(boolean)函数设置这个dialog为不可取消(用户就不能通过按返回键关闭这个dialog)。使用set...Button()方法添加button,例如,使用接收在button上显示的字符串和对用户按下按钮动作进行处理的DialogInterface.OnClickListener这两个参数的setPositiveButton()方法为dialog添加一个按钮。

  

  注意:不可以在一个dialog上同时添加两个“positive” button。最多可以在一个dialog上添加三个button:positive, neutral, and negative button。

  添加列表:

  使用setItems()方法为AlertDialog添加一个可供用户选择的列表。

  view plaincopy to clipboardprint?

  final CharSequence[] items = {"Red", "Green", "Blue"};

  AlertDialog.Builder builder = new AlertDialog.Builder(this);

  builder.setTitle("Pick a color");

  builder.setItems(items, new DialogInterface.OnClickListener() {

  public void onClick(DialogInterface dialog, int item) {

  Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();

  }

  });

  AlertDialog alert = builder.create();

  final CharSequence[] items = {"Red", "Green", "Blue"};

  AlertDialog.Builder builder = new AlertDialog.Builder(this);

  builder.setTitle("Pick a color");

  builder.setItems(items, new DialogInterface.OnClickListener() {

  public void onClick(DialogInterface dialog, int item) {

  Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();

  }

  });

  AlertDialog alert = builder.create();

  AlertDialog alert = builder.create();

  首先,调用setTitle(CharSequence)为dialog添加一个title。然后,调用 setItems()为dialog添加一个list,这个list接收一组items以显示,并且 DialogInterface.OnClickListener对用户的不同选择进行处理。

  添加checkboxes和radio buttons

  为了创建带有multiple-choice items(checkboxes)或single-choice items(radio buttons)的dialog,需要分别使用setMultiChoiceItems()和setSingleChoiceItems()方法。如果你是在onCreateDialog创建这些可选list,Android就会为你管理这个list的状态。只要这个Activity是active的,这个dialog就会记住之前被用户选中的items,但当用户离开当前Activity,the selection 就会丢失。

  注意:为了在用户离开或者暂停Activity时保存selection,在整个Activity的生命周期中,你一定要在的适当的时候sava和restore

  

the setting。如果想要永久保存the selections,就需要使用数据存储技术保存这些setting.

  要创建一个带有single-choice items的AlertDialog,可以使用创建带有lists的AlertDialog的代码段,但是,需要用setSingleChoiceItems()代替setItems()。

  view plaincopy to clipboardprint?

  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() {

  public void onClick(DialogInterface dialog, int item) {

  Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();

  }

  });

  AlertDialog alert = builder.create();

  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() {

  public void onClick(DialogInterface dialog, int item) {

  Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();

  }

  });

  AlertDialog alert = builder.create();

  setSingleChoiceItems()的第二个参数是一个整数值,指示默认默认选中哪个list(zero-based),使用“-1”指示默认情况下不应该选中任何item。

  创建ProgressDialog

  一个ProcessDialog是一个扩展了的AlertDialog类,一个实例化了ProcessDialog的dialog能够显示一个一个进度条,同时也能够提供buttons,例如取消下载的button。

  只要呼叫ProgressDialog.show()就可以打开一个progress dialog。

  ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "",

  "Loading. Please wait...", true);

  第一个参数是该应用程序的Context,第二个参数是这个dialog的title(留白),第三个参数是显示在dialog上的字符串,最后一个参数标识这个progress是否是indeterminate(这只和进度条的创建相关,我们将在一下节中讨论)。

  

  进度dialog的默认方格是将进度显示为一个圆环。如果你要创建一个可以显示下载进程的进度条,请阅读一下内容。

  显示进度条

  要想显示带有动态进度信息的进度条,你需要:

  1. 调用ProgressDialog(Context)这个构造函数初始化ProgressDialog。

  2. 调用setProgressStyle(int)将进度条的风格设置为STYLE_HORIZONTAL。当然,你也可以给这个dialog设置其它属性,例如在它上面显示一条消息。

  3. 当你准备好去显示一个dialog了,可以调用show()方法,或者从onCreateDialog(int)这个回调方法中返回ProgressDialog。

  4. 你可以调用并传递一个目前总完成百分比的整数值给setProgress(int),或者调用并传递一个你想要加到目前已完成百分比的整数值给incrementProgressBy(int)。

  例如,你可能像这样创建ProgressDialog。

  view plaincopy to clipboardprint?

  ProgressDialog progressDialog;

  progressDialog = new ProgressDialog(mContext);

  progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

  progressDialog.setMessage("Loading...");

  progressDialog.setCancelable(false);

  ProgressDialog progressDialog;

  progressDialog = new ProgressDialog(mContext);

  progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

  progressDialog.setMessage("Loading...");

  progressDialog.setCancelable(false);

  大多数创建progress dialog的代码都会同时创建一个用于更新这个progress dialog的线程。为了完成更新progress dialog的任务,你需要在你的应用程序中再开启一个线程,然后使用Handler对象向Activity的UI线程传递进度信息。如果你还没有熟练使用带有Handler的新加线程,请看下面的新启一个线程更新progress dialog的例子。

  包含新启线程的ProgressDialog

  这个例子使用一个新启动的线程跟踪进度(实际上只是将数值累加到100)信息,每当有了新的进度,这个新启的线程就使用Handler向主Activity发送一条Message,然后主Acitvity就会更新ProgressDialog。

  view plaincopy to clipboardprint?

  package org.vhow.android.ui.dialogs;

  

  import android.app.Activity;

  import android.app.Dialog;

  import android.app.ProgressDialog;

  import android.os.Bundle;

  import android.os.Handler;

  import android.os.Message;

  import android.util.Log;

  import android.view.View;

  import android.view.View.OnClickListener;

  import android.widget.Button;

  public class Dialogs extends Activity

  {

  static final int PROGRESS_DIALOG = 0;

  Button button;

  ProgressThread progressThread;

  ProgressDialog progressDialog;

  @Override

  public void onCreate(Bundle savedInstanceState)

  {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.main);

  // setup the button that starts the progress dialog

  button = (Button) findViewById(R.id.progressDialog);

  button.setOnClickListener(new OnClickListener()

  {

  @Override

  public void onClick(View v)

  {

  showDialog(PROGRESS_DIALOG);

  }

  });

  }

  @Override

  protected Dialog onCreateDialog(int id)

  {

  switch (id)

  {

  case PROGRESS_DIALOG:

  progressDialog = new ProgressDialog(Dialogs.this);

  progressDialog

  .setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

  progressDialog.setMessage("Loading...");

  progressThread = new ProgressThread(handler);

  progressThread.start();

  return progressDialog;

  default:

  return null;

  }

  }

  // Define the Handler that receives messages from the thread and update the

  // progress

  final Handler handler = new Handler()

  {

  public void handleMessage(Message msg)

  {

  

  int total = msg.getData().getInt("total");

  progressDialog.setProgress(total);

  if (total >= 100)

  {

  dismissDialog(PROGRESS_DIALOG);

  progressThread.setState(ProgressThread.STATE_DONE);

  }

  }

  };

  /**

  * Nested class that performs progress calculations(counting)

  */

  private class ProgressThread extends Thread

  {

  Handler mHandler;

  final static int STATE_DONE = 0;

  final static int STATE_RUNNING = 1;

  int mState;

  int total;

  ProgressThread(Handler h)

  {

  mHandler = h;

  }

  public void run()

  {

  mState = STATE_RUNNING;

  total = 0;

  while (mState == STATE_RUNNING)

  {

  try

  {

  Thread.sleep(100);

  }

  catch (InterruptedException e)

  {

  Log.e("ERROR", "Thread Interrupted");

  }

  Message msg = mHandler.obtainMessage();

  Bundle b = new Bundle();

  b.putInt("total", total);

  msg.setData(b);

  mHandler.sendMessage(msg);

  total++;

  }

  }

  /**

  * sets the current state for the thread, used to stop teh thread

  */

  public void setState(int state)

  {

  mState = state;

  }

  }

  }

  package org.vhow.android.ui.dialogs;

  import android.app.Activity;

  import android.app.Dialog;

  import android.app.ProgressDialog;

  import android.os.Bundle;

  import android.os.Handler;

  import android.os.Message;

  import android.util.Log;

  import android.view.View;

  import android.view.View.OnClickListener;

  import android.widget.Button;

  

  public class Dialogs extends Activity

  {

  static final int PROGRESS_DIALOG = 0;

  Button button;

  ProgressThread progressThread;

  ProgressDialog progressDialog;

  @Override

  public void onCreate(Bundle savedInstanceState)

  {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.main);

  // setup the button that starts the progress dialog

  button = (Button) findViewById(R.id.progressDialog);

  button.setOnClickListener(new OnClickListener()

  {

  @Override

  public void onClick(View v)

  {

  showDialog(PROGRESS_DIALOG);

  }

  });

  }

  @Override

  protected Dialog onCreateDialog(int id)

  {

  switch (id)

  {

  case PROGRESS_DIALOG:

  progressDialog = new ProgressDialog(Dialogs.this);

  progressDialog

  .setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

  progressDialog.setMessage("Loading...");

  progressThread = new ProgressThread(handler);

  progressThread.start();

  return progressDialog;

  default:

  return null;

  }

  }

  // Define the Handler that receives messages from the thread and update the

  // progress

  final Handler handler = new Handler()

  {

  public void handleMessage(Message msg)

  {

  int total = msg.getData().getInt("total");

  progressDialog.setProgress(total);

  if (total >= 100)

  {

  dismissDialog(PROGRESS_DIALOG);

  progressThread.setState(ProgressThread.STATE_DONE);

  }

  }

  };

  /**

  * Nested class that performs progress calculations(counting)

  */

  private class ProgressThread extends Thread

  

  {

  Handler mHandler;

  final static int STATE_DONE = 0;

  final static int STATE_RUNNING = 1;

  int mState;

  int total;

  ProgressThread(Handler h)

  {

  mHandler = h;

  }

  public void run()

  {

  mState = STATE_RUNNING;

  total = 0;

  while (mState == STATE_RUNNING)

  {

  try

  {

  Thread.sleep(100);

  }

  catch (InterruptedException e)

  {

  Log.e("ERROR", "Thread Interrupted");

  }

  Message msg = mHandler.obtainMessage();

  Bundle b = new Bundle();

  b.putInt("total", total);

  msg.setData(b);

  mHandler.sendMessage(msg);

  total++;

  }

  }

  /**

  * sets the current state for the thread, used to stop teh thread

  */

  public void setState(int state)

  {

  mState = state;

  }

  }

  }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值