【问题标题】:Android AlertDialog with dynamically changing text on every requestAndroid AlertDialog 在每个请求上动态更改文本
【发布时间】:2010-10-31 13:58:30
【问题描述】:

我想显示一个带有一个选项的 AlertDialog,该选项可能会随每个请求而改变。因此,例如,有一次我想显示“添加到联系人”选项,而另一次应该是“从联系人中删除”。

我的代码第一次确实可以运行,但是 Android 似乎缓存了 AlertDialog 以便下次不会执行 onCreateDialog。因此选项不再改变。我可以阻止这种缓存,还是有另一种更改选项的方法?

我正在使用 SDK 1.5,但使用的是 1.1。

@Override
protected Dialog onCreateDialog(final int id) {
    ...
    String add_remove_contact = res.getString(R.string.profile_add_to_contacts);
    if (user.getContacts().contains(profileID)) {
        add_remove_contact = res.getString(R.string.profile_remove_from_contacts);
        // TODO: this string is not changed when contact status changes 
    }
    final CharSequence[] items = {res.getString(R.string.view_profile),
                                  res.getString(R.string.profile_send_message),
                                  add_remove_contact};
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    ...
    return builder.create();
}

【问题讨论】:

    标签: java android android-alertdialog


    【解决方案1】:

    查看onPrepareDialog 方法,该方法将在显示对话框之前调用。在那里您可以根据请求类型更改所需的值。

    日期选择器示例

    @Override
    protected Dialog onCreateDialog(final int id) {
      switch (id) {
      case DIALOG_DATE_ID:
        final Calendar c = Calendar.getInstance();
        return new DatePickerDialog(this, this, c.get(Calendar.YEAR),
                                    c.get(Calendar.MONTH), 
                                    c.get(Calendar.DAY_OF_MONTH));
      default:
        return super.onCreateDialog(id);
      }
    }
    
    @Override
    protected void onPrepareDialog(final int id, final Dialog dialog) {
      switch (id) {
      case DIALOG_DATE_ID:
        //update to current time
        final Calendar c = Calendar.getInstance();
        ((DatePickerDialog) dialog).updateDate(c.get(Calendar.YEAR), 
                                               c.get(Calendar.MONTH), 
                                               c.get(Calendar.DAY_OF_MONTH));
        break;
      }
    }
    

    【讨论】:

    • onPrepareDialog 是更新对话框的好地方。但是如何更改 onPrepareDialog 中的 AlertDialogs 项?似乎没有任何方法可以解决这个问题,我找不到与 findViewById 一起使用的 id。
    • 您不需要“findViewById”,因为您的对话框是作为参数传递的。当您想使用任何特定于 AlertDialog 的方法(例如“setMessage”)时,您必须强制转换它。
    • 一年多后,我发现这段代码“正常工作”。你几乎不需要调整它!谢谢你。我看到了 Android 开发指南,但它几乎没有说明如何充分使用 onPrepareDialog。您的示例效果很好。
    • 蒂姆,你没有回答乌尔里希。他在问如何更新对话框内的内容,而不是对话框本身。我认为它与 DatePickerDialog 的工作方式非常不同。
    【解决方案2】:

    你也可以使用Activity的removeDialog(int)函数。当对话框被关闭时,Activity 基本上存储对话框的状态(出于性能原因,我想)。在对话框上调用 removeDialog(int) 会强制 Activity 卸载对话框的所有引用,并在显示时将其从屏幕上关闭。

    Creating Dialogs
    Activity#removeDialog(int)

    【讨论】:

    • 对话框只需要创建一次,出于性能原因(这是一个相对昂贵的操作)。您可以使用 onPrepareDialog 方法在显示对话框时对其进行更改,而不是每次显示时都重新创建它,如下一个答案中所述。
    • 对于那些仍然来这里的人,removeDialogshowDialog 现在已弃用。随着 Android 移至 Fragments,现在建议使用 DialogFragment。更多信息,这里是官方文档的链接:developer.android.com/reference/android/app/DialogFragment.html
    【解决方案3】:

    这是这个问题的重复: Android: Can not change the text appears in AlertDialog

    您也可以这样做: http://andmobidev.blogspot.com/2010/03/modifying-alert-dialogs-list-items.html

    似乎确实会减慢长按菜单的显示速度...

    【讨论】:

      【解决方案4】:

      我想我已经解决了上述不一致的行为。最初创建对话框时(当它仍然是 AlertDialog.Builder 时),您必须将消息设置为初始状态(非空),否则 onPrepareDialog 不会用预期值覆盖它。因此,当您创建对话框时,请执行以下操作以在消息中始终包含非空值。我为此苦苦挣扎了几天,偶然发现了这个解决方案:

      AlertDialog.Builder resultAlert = new AlertDialog.Builder(context);
      
      if ( message == null ) {
          resultAlert.setMessage("");
      } else {
          resultAlert.setMessage(message);
      }
      

      【讨论】:

      【解决方案5】:

      当您有自定义对话框时,您可以使用 dialog.getWindow().findViewById(...) 更改自定义项

      此示例保存最后显示的文本,并在下次显示对话框时再次显示。

      // custom dialog
      final Dialog dialog = new Dialog(this);
      dialog.setContentView(R.layout.customized);
      
      dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
          @Override
          public void onDismiss(DialogInterface dialogInterface) {
             EditText dialogText = (EditText)dialog.getWindow().findViewById(R.id.customText);
             savedText = dialogText.getText();
          }
      });
      
      dialog.show();
      EditText dialogText = (EditText)dialog.getWindow().findViewById(R.id.customText);
      dialogText.setText(savedText);
      

      自定义对话框的xml:

      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout 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">
      
      <Button
          android:id="@+id/buttonOK"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="OK"
          android:layout_alignParentBottom="true"
          android:layout_alignParentLeft="true"
          android:layout_alignParentStart="true"
          android:layout_marginBottom="16dp" />
      
      <EditText
          android:id="@+id/customText"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginTop="19dp"
          android:hint="Message"
          android:ems="10"
          android:layout_alignParentTop="true"
          android:layout_centerHorizontal="true" />
      

      【讨论】:

        【解决方案6】:

        我了解使用活动管理对话框的性能原因,但建议不要使用它们,除非是简单的情况。原因如下:

        1. Bundle 参数仅在 API 级别 8 中添加,因此不能用于向后兼容。这实际上意味着“onPrepareDialog”需要依赖非局部变量来实现状态差异;

        2. 实践表明在响应“onPrepareDialog”主体中所做的任何对话框更改时行为不佳且不一致。

        如果根据需要对对话框进行子类化和创建,则不会出现这些困难。如有必要,可以调用“setOwnerActivity”。

        【讨论】:

          【解决方案7】:

          我有一个想法,但不是很好。*这在用户不经常使用对话框时使用!*解决方案:首先,您应该声明一个变量(int 类型) 并将默认值设为0。如private int i=0; 在使用 Activity 的 showDialog 方法之前,增加 int 变量 i 并将值 i 作为参数作为 showDialog 方法发布。 代码可能是这样的

          private int i=0;
          
          //before you show the dialog
          this.i++;
          this.showDialog(this.i);
          

          【讨论】:

          • 如你所说,这不太好。 :) 这种方法是不必要和浪费的。如果你想下次创建一个新的对话框,你应该使用 removeDialog()。
          【解决方案8】:

          没错。对于使用Builder.create()onPrepareDialog() 创建的 AlertDialog,它是无用的。 Builder 是单向的,一旦创建了对话框,就无法更新。我的意思是不能松散,我相信您可以处理视图并手动完成所有操作,但这首先破坏了使用构建器的意义。

          我找到的唯一解决方案是手动创建/显示/关闭对话框,而不是使用onCreateDialog()showDialog() 等。我尝试调用removeDialog(),但这似乎不起作用。

          【讨论】:

          • 错了。如果将给定的 Dialog 转换为更具体的类型,例如 AlertDialog,则可以使用 setMessage 更新消息等属性。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-09-05
          • 1970-01-01
          • 1970-01-01
          • 2013-01-06
          • 1970-01-01
          • 2010-10-24
          • 2015-05-25
          相关资源
          最近更新 更多