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 方法在显示对话框时对其进行更改,而不是每次显示时都重新创建它,如下一个答案中所述。 对于那些仍然来这里的人,removeDialog
和 showDialog
现在已弃用。随着 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?