Подтвердить что ты не робот

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

Я хочу показать 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();
}
4b9b3361

Ответ 1

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

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

Ответ 2

Посмотрите 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;
  }
}

Ответ 4

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

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

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

Ответ 5

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

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

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

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

Ответ 6

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

Ответ 7

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

private int i=0;

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

Ответ 8

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

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