2009-06-05 2 views
22

Я хочу показать AlertDialog с одним вариантом, который может измениться при каждом запросе. Например, когда-то я хочу показать опцию «добавить к контактам», а в другой раз - «удалить из контактов».Android 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(); 
} 

ответ

19

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

Creating Dialogs
Activity#removeDialog(int)

+9

Диалог нужно создать только один раз, по соображениям производительности (это относительно дорогостоящая операция). Вместо того, чтобы воссоздавать его каждый раз отображается, вы можете использовать метод onPrepareDialog для внесения изменений в диалог, как он отображается, как объясняется в следующем ответе. – ChrisV

+0

Для тех, кто все еще здесь, 'removeDialog' и' showDialog' теперь устарели. Когда Android переместился в «Фрагменты», теперь рекомендуется использовать «DialogFragment». Для получения дополнительной информации см. Ссылку на официальную документацию: http://developer.android.com/reference/android/app/DialogFragment.html –

+0

«removeDialog» устарел, просто говоря ... –

33

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

onPrepareDialog является хорошим местом, чтобы обновить диалоговое окно. Но как я могу изменить элементы AlertDialogs в onPrepareDialog? Для этого не существует никакого метода, и я не могу найти id для использования с findViewById. –

+3

Вам не нужно «findViewById», так как ваш диалог передается в качестве аргумента. Если вы хотите использовать любой специальный метод AlertDialog, например «setMessage», вы должны его использовать. –

+0

Более года спустя я обнаружил, что этот код «просто работает». Вам практически не нужно даже настраивать его! Спасибо. Я видел руководство Android dev, но он едва говорит, как полностью использовать onPrepareDialog. Ваш пример отлично работал. – davidcesarino

-3

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

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

+6

Это неправильно. Вы можете обновлять такие свойства, как сообщение, используя setMessage, если вы задали данный диалог более конкретному типу, например AlertDialog. –

1

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

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

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

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

4

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

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

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

Вы правы. Эта ошибка отслеживается здесь: https://code.google.com/p/android/issues/detail?id=6489 – TalkLittle

-1

И я получил идею, но не так хорошо * Это используется, когда пользователи не используют диалог довольно часто.! * Решение: во-первых, вы должны объявить переменную (тип 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); 
+3

Как вы говорите, это не так хорошо. :) Этот подход не нужен и расточителен. Вы должны использовать removeDialog(), если вы хотите создать новый новый диалог в следующий раз. –

0

Если у вас есть диалог на заказ вы можете изменить пользовательские элементы с помощью 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 Customized Диалог:

<?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" />