2009-06-05 11 views
22

Voglio mostrare un AlertDialog con un'opzione che potrebbe cambiare ad ogni richiesta. Quindi ad esempio una volta voglio mostrare l'opzione "aggiungi ai contatti" mentre un'altra volta dovrebbe essere "rimuovi dai contatti".Android AlertDialog con testo che cambia dinamicamente ad ogni richiesta

Il mio codice funziona per la prima volta, tuttavia Android sembra memorizzare nella cache AlertDialog in modo che onCreateDialog non venga eseguito la volta successiva. Pertanto l'opzione non cambia più. Posso evitare questa memorizzazione nella cache o esiste solo un altro modo di modificare l'opzione?

Sto lavorando con SDK 1.5 ma utilizzando 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(); 
} 

risposta

19

È inoltre possibile utilizzare il removeDialog (int) funzione dell'attività. Quando una finestra di dialogo viene chiusa, l'attività memorizza fondamentalmente lo stato della finestra di dialogo (per motivi di prestazioni che immagino). Chiamando removeDialog (int) sulla finestra di dialogo forza l'attività a scaricare tutti i riferimenti per la finestra di dialogo e lo chiude dallo schermo se viene mostrato.

Creating Dialogs
Activity#removeDialog(int)

+9

La finestra di dialogo deve essere creata solo una volta, per motivi di prestazioni (è un'operazione relativamente costosa). Invece di ricrearlo ogni volta che viene visualizzato, è possibile utilizzare il metodo onPrepareDialog per apportare modifiche alla finestra di dialogo così come viene visualizzata, come spiegato nella risposta successiva. – ChrisV

+0

Per quelli che ancora arrivano qui, 'removeDialog' e' showDialog' sono ora deprecati. Mentre Android si sposta su 'Fragments', l'uso di' DialogFragment' è ora raccomandato. Per ulteriori informazioni, ecco un link alla documentazione ufficiale: http://developer.android.com/reference/android/app/DialogFragment.html –

+0

"removeDialog" è deprecato, solo dicendo ... –

33

Date un'occhiata a onPrepareDialog metodo che verrà chiamato prima che venga mostrata la finestra. È possibile modificare i valori richiesti in base al tipo di richiesta.

Esempio con selezione data

@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 è un buon posto per aggiornare la finestra di dialogo. Ma come posso modificare gli elementi AlertDialogs in onPrepareDialog? Non sembra esserci alcun metodo per questo e non riesco a trovare un id da utilizzare con findViewById. –

+3

Non hai bisogno di "findViewById" poiché la tua finestra di dialogo è passata come argomento. Quando vuoi usare un metodo specifico di AlertDialog come "setMessage" devi lanciarlo. –

+0

Più di un anno dopo ho scoperto che questo codice "funziona". Praticamente non hai nemmeno bisogno di modificarlo! Grazie. Ho visto la guida di sviluppo di Android, ma a malapena indica come utilizzare onPrepareDialog. Il tuo esempio ha funzionato alla grande. – davidcesarino

-3

esattamente. per AlertDialog, che è stato creato con Builder.create(), onPrepareDialog() è inutile. Il builder è a senso unico in quanto una volta creata la finestra di dialogo, non è possibile aggiornarla. Voglio dire non può in modo approssimativo, sono sicuro che si potrebbe ottenere una maniglia per la vista e fare tutto manualmente, ma che sconfigge il punto di utilizzare il costruttore in primo luogo.

l'unica soluzione che ho trovato è stato quello di creare manualmente/mostra/chiudere la finestra invece di usare onCreateDialog(), showDialog(), ecc Ho provato a chiamare removeDialog(), ma che non sembrano funzionare.

+6

Questo è sbagliato. È possibile aggiornare proprietà come il messaggio utilizzando setMessage se si esegue il cast della finestra di dialogo specificata su un tipo più specifico, ad esempio AlertDialog. –

1

Capisco i motivi delle prestazioni per l'utilizzo di finestre di dialogo gestite dall'attività, ma raccomanderei che non vengano utilizzati ad eccezione dei casi semplici. Le ragioni di questo sono:

  1. L'argomento Fascio fu aggiunto soltanto nel API livello 8, quindi non può essere adottata per la compatibilità all'indietro. Ciò significa in effetti che "onPrepareDialog" deve fare affidamento su variabili non locali per le differenze di stato;

  2. La pratica indica un comportamento scarso e incoerente in risposta a qualsiasi modifica di dialogo effettuata nel corpo di 'onPrepareDialog'.

Nessuna di queste difficoltà si verifica se le finestre di dialogo sono sottoclasse e create in base alle esigenze. 'setOwnerActivity' può essere chiamato se necessario.

4

Penso di avere una soluzione per il comportamento incoerente di cui sopra. Quando si crea inizialmente la finestra di dialogo (quando è ancora un AlertDialog.Builder), è necessario impostare il messaggio su uno stato iniziale (non nullo) o suPrepareDialog NON lo sovrascrive con il valore previsto. Quindi, quando crei la finestra di dialogo, fai qualcosa di simile per avere sempre un valore non nullo nel messaggio. Ho lottato con questo per giorni e ho trovato questa soluzione per caso:

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

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

Hai ragione. Questo bug è tracciato qui: https://code.google.com/p/android/issues/detail?id=6489 – TalkLittle

-1

E ho avuto un idea, ma non così buono * Questo viene utilizzato quando gli utenti non utilizzano la finestra di dialogo con una certa frequenza.! * La soluzione: in primo luogo, è necessario dichiarare una variabile (tipo int) e impostare il valore predefinito come 0.such come private int i=0; e prima di utilizzare i metodi showDialog di Activity, aumentare la variabile int i e inserire il valore i come parametro come metodo showDialog. il codice può piacere questo

private int i=0; 

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

Come dici tu, non va molto bene. :) Questo approccio è inutile e dispendioso. Dovresti usare removeDialog() se vuoi creare una nuova finestra di dialogo la prossima volta. –

0

Quando si ha una finestra di dialogo personalizzata è possibile modificare gli oggetti personalizzati utilizzando dialog.getWindow(). FindViewById (...)

Questo esempio salvare l'ultimo testo mostrato e visualizzalo di nuovo la prossima volta che mostri la finestra di dialogo.

// 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 di dialogo personalizzato:

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

Problemi correlati