Android AlertDialog 在每个请求上动态更改文本

Posted

技术标签:

【中文标题】Android AlertDialog 在每个请求上动态更改文本【英文标题】:Android AlertDialog with dynamically changing text on every request 【发布时间】: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();

【问题讨论】:

【参考方案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 DialogsActivity#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);

【讨论】:

你是对的。此处跟踪此错误:code.google.com/p/android/issues/detail?id=6489【参考方案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_
    android:layout_>

<Button
    android:id="@+id/buttonOK"
    android:layout_
    android:layout_
    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_
    android:layout_
    android:layout_marginTop="19dp"
    android:hint="Message"
    android:ems="10"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true" />

【讨论】:

【参考方案6】:

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

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

    实践表明在响应“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 更新消息等属性。

以上是关于Android AlertDialog 在每个请求上动态更改文本的主要内容,如果未能解决你的问题,请参考以下文章

Android:如何在 PIP 模式下显示 AlertDialog?

转载android AlertDialog

如何在 Android 中设置 AlertDialog 的大小? [复制]

Android AlertDialog

如何在android中关闭AlertDialog

Android:如何设置AlertDialog的宽度和高度,以及AlertDialog风格的按钮?