Android AlertDialog с динамически изменяющимся текстом при каждом запросе

StackOverflow https://stackoverflow.com/questions/954726

Вопрос

Я хочу показать 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();
}
Это было полезно?

Решение

Вы также можете использовать удалитьДиалог (целое) Функция Действия.Когда диалог закрывается, Activity в основном сохраняет состояние диалога (я полагаю, из соображений производительности).Вызов удалитьДиалог (целое) в диалоговом окне заставляет действие выгружать все ссылки на диалоговое окно и убирает его с экрана, если оно отображается.

Создание диалогов
Действие#removeDialog(int)

Другие советы

Взгляни на 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;
  }
}

Это дубликат этого вопроса:Андроид:Невозможно изменить текст, отображаемый в AlertDialog.

Вы также можете сделать это следующим образом:http://andmobidev.blogspot.com/2010/03/modifying-alert-dialogs-list-items.html

Хотя, похоже, замедляется отображение меню при длительном нажатии...

Я думаю, что у меня есть решение непоследовательного поведения, упомянутого выше.При первоначальном создании диалога (когда он все еще является AlertDialog.Builder) вам необходимо установить для сообщения начальное состояние (не нулевое), иначе onPrepareDialog НЕ перезапишет его предполагаемым значением.Поэтому, когда вы создаете диалог, сделайте что-то подобное, чтобы в сообщении всегда было ненулевое значение.Я боролся с этим несколько дней и случайно нашел это решение:

AlertDialog.Builder resultAlert = new AlertDialog.Builder(context);

if ( message == null ) {
    resultAlert.setMessage("");
} else {
    resultAlert.setMessage(message);
}

Я понимаю причины повышения производительности использования диалоговых окон, управляемых действиями, но рекомендую не использовать их, за исключением простых случаев.Причинами этого являются:

  1. Аргумент Bundle был добавлен только на уровне API 8, поэтому его нельзя использовать для обратной совместимости.Фактически это означает, что onPrepareDialog должен полагаться на нелокальные переменные для определения различий в состоянии;

  2. Практика указывает на плохое и непоследовательное поведение в ответ на любые изменения диалога, внесенные в тело onPrepareDialog.

Ни одна из этих трудностей не возникает, если Диалоги подразделяются на подклассы и создаются по мере необходимости.При необходимости можно вызвать setOwnerActivity.

Если у вас есть настраиваемый диалог, вы можете изменять настраиваемые элементы с помощью диалога.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" />

И у меня появилась идея, но не очень хорошая.*Это используется, когда пользователи не используют диалоговое окно довольно часто!* Решение: сначала вам следует объявить переменную (тип int) и установить значение по умолчанию 0. Например, private int i=0;и прежде чем использовать методы showDialog Activity, увеличьте переменную int i и опубликуйте значение i в качестве параметра в качестве метода showDialog.коду может понравиться это

private int i=0;

//before you show the dialog
this.i++;
this.showDialog(this.i);

точно.для AlertDialog, который был создан с помощью Builder.create(), onPrepareDialog() бесполезно.Builder является односторонним: после создания диалогового окна его нельзя обновить.я имею в виду, что не могу свободно, я уверен, что вы могли бы получить дескриптор представления и сделать все это вручную, но это в первую очередь лишает смысла использовать конструктор.

единственное решение, которое я нашел, - это вручную создать/показать/закрыть диалог вместо использования onCreateDialog(), showDialog(), и т. д.я пытался позвонить removeDialog(), но это, похоже, не сработало.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top