2012-05-26 6 views
9

Sembra non esserci un modo semplice per ottenere una finestra di dialogo di avviso per restituire un valore semplice.
Questo codice non funziona (la variabile risposta non può essere impostato dall'interno l'ascoltatore, in realtà non ha nemmeno compilare)Finestra di dialogo di conferma Android che restituisce vero o falso

public static boolean Confirm(Context context) { 
    boolean answer; 
    AlertDialog dialog = new AlertDialog.Builder(context).create(); 
    dialog.setTitle("Confirmation"); 
    dialog.setMessage("Choose Yes or No"); 
    dialog.setCancelable(false); 
    dialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int buttonId) { 
      answer = true; 
     } 
    }); 
    dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "No", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int buttonId) { 
      answer = false; 
     } 
    }); 
    dialog.setIcon(android.R.drawable.ic_dialog_alert); 
    dialog.show(); 
    return answer; 
} 

NOTA: E 'importante che il metodo è auto contenuto, cioè, non dipende da variabili o costrutti esterni ad esso. Basta chiamarlo e ottenere la tua risposta, vero o falso.

Quindi, cosa fare? Questo semplice desiderio di restituire true o false sembra essere molto più complicato di quanto meriti.

Inoltre, il metodo setButton ha la forma:

dialog.setButton(int buttonId, String buttonText, Message msg) 

ma non è chiaro come usarlo, in cui è il meesage inviato, a chi, quale gestore viene utilizzato?

risposta

9

Beh, ero dirò che sono molto contento di me stesso perché ho trovato una risposta semplice, tutta da sola!
Ma la verità è che anche se trovo un modo per restituire un valore (che mostro di seguito). È inutile.

Il vero problema è che volevo una finestra di dialogo sincrona, una finestra di dialogo che aspetta che l'utente risponda prima di riprendere il codice dopo dialog.show().
Non esiste una tale bestia in Android. Tutte le finestre di dialogo sono asincrone, quindi dialog.show() invia solo la finestra di dialogo in qualche coda (credo) e continua. In questo modo non ottieni la tua risposta in tempo.

Per tutto il suo valore (nulla) qui di seguito troverete come impostare un valore all'interno del metodo che costruisce la finestra di dialogo. Forse ci sono altri usi per questa tecnica, non legati al ciclo di vita della finestra di dialogo.




di dare qualche informazioni correlate, dirò che se si sostituisce

boolean answer; 

con

final boolean answer; 

è possibile accedere alla variabile da all'interno del listener, ma non è possibile assegnargli un nuovo valore, poiché è stato dichiarato come finale.

Ecco che arriva il trucco.
Definire la variabile come:

final boolean[] answer = new boolean[1]; 

Alcuni di voi già vedere perché questo funzionerà. La variabile finale qui non è il singolo elemento dell'array booleano, è l'array stesso.
Quindi ora è possibile assegnare l'elemento dell'array [0] come si desidera.

dialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() { 
    public void onClick(DialogInterface dialog, int buttonId) { 
     answer[0] = true; 
    } 
}); 
. . . 
return answer[0]; 

Infine, è possibile restituirlo dal metodo.

+0

Hai mai trovato una soluzione migliore? – Lion789

+1

@ Lion789 Come ho affermato, questa non è davvero una soluzione e ho spiegato perché con l'attuale sistema operativo Android non ci può essere un'anima. Quindi, in breve, non ho trovato una soluzione migliore. Secondo Android, dovresti inserire il codice nel listener onClick() per la finestra di dialogo. Questo è l'unico modo per eseguirlo dopo aver chiuso la finestra di dialogo. – ilomambo

+0

iLomambo Hai provato quello sulla parte superiore con chiamando Runnable – Lion789

0

Dichiarare un campo "risposta" nella propria attività e impostarne un valore. I campi di una classe sono visibili alle classi interne, quindi puoi farlo.

+0

Sì .. Io non ne ha parlato, ma ho bisogno del metodo per essere indipendente della classe è definito in . Impossibile usare una variabile di classe. Aggiornerò la domanda per renderla più chiara. – ilomambo

3

Che cosa si può fare è creare un listener per la finestra di dialogo dell'avviso che ascolta all'azione AlertDialogs utilizzando un'interfaccia.

Creare un'interfaccia.

public class MyInterface { 

    DialogReturn dialogReturn; 

    public interface DialogReturn { 

     void onDialogCompleted(boolean answer); 
    } 

    public void setListener(DialogReturn dialogReturn) { 
     this.dialogReturn = dialogReturn; 
    } 

    public DialogReturn getListener() { 
     return dialogReturn; 

    } 
} 

Ora, nella tua classe basta implementare l'interfaccia che si è creato utilizzando implements MyInterface.DialogReturn

quindi è possibile impostare l'ascoltatore e farlo funzionare come mostrato di seguito,

public class Main extends Activity implements MyInterface.DialogReturn{ 

    MyInterface myInterface; 
    MyInterface.DialogReturn dialogReturn; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
       .... 
     myInterface = new MyInterface(); 
     myInterface.setListener(this); 
    } 


    public void Confirm(Context context) { 
     AlertDialog dialog = new AlertDialog.Builder(context).create(); 
     dialog.setTitle("Confirmation"); 
     dialog.setMessage("Choose Yes or No"); 
     dialog.setCancelable(false); 
     dialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int buttonId) { 
       myInterface.getListener().onDialogCompleted(true); 
      } 
     }); 
     dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "No", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int buttonId) { 
       myInterface.getListener().onDialogCompleted(false); 
      } 
     }); 
     dialog.setIcon(android.R.drawable.ic_dialog_alert); 
     dialog.show(); 
     } 


@Override 
    public void onDialogCompleted(boolean answer) { 
     Toast.makeText(Main.this, answer+"", Toast.LENGTH_LONG).show(); 
      if(answer) 
      // do something 
      else 
      // do something 
    } 
} 
+0

Sto assumendo che il tuo suggerimento funzioni. Ma, che modo complicato per ottenere una cosa semplice! Non pensi? – ilomambo

+0

Ya vero, ma questo non è molto complicato se lo capiamo una volta e lo facciamo funzionare. –

+2

@ilomambo Benvenuto in Android! Benvenuti in Java per questo.

14

ho un problema simile a questo in questo forum, ma alla fine ottengo la mia risposta. il mio problema in quel post è come creare classi di dialogo di conferma separate che possono accedere ad altre classi o attività, quindi con la classe di dialogo di conferma non è necessario scrivere codice lungo.

ecco la mia risposta.

In primo luogo è necessario creare DialogHandler.java

import android.app.Activity; 
import android.app.AlertDialog; 
import android.content.Context; 
import android.content.DialogInterface; 
import src.app.R; 

public class DialogHandler { 
    public Runnable ans_true = null; 
    public Runnable ans_false = null; 

    // Dialog. -------------------------------------------------------------- 

    public boolean Confirm(Activity act, String Title, String ConfirmText, 
      String CancelBtn, String OkBtn, Runnable aProcedure, Runnable bProcedure) { 
     ans_true = aProcedure; 
     ans_false= bProcedure; 
     AlertDialog dialog = new AlertDialog.Builder(act).create(); 
     dialog.setTitle(Title); 
     dialog.setMessage(ConfirmText); 
     dialog.setCancelable(false); 
     dialog.setButton(DialogInterface.BUTTON_POSITIVE, OkBtn, 
       new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int buttonId) { 
         ans_true.run(); 
        } 
       }); 
     dialog.setButton(DialogInterface.BUTTON_NEGATIVE, CancelBtn, 
       new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int buttonId) { 
         ans_false.run(); 
        } 
       }); 
     dialog.setIcon(android.R.drawable.ic_dialog_alert); 
     dialog.show(); 
     return true; 
    } 
} 

e questo è esempio per chiamare in un'altra classe

public class YourActivity extends Activity { 
    /** Called when the activity is first created. */ 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     findViewById(R.id.button1).setOnClickListener(myclick); 
    } 

    public final Button.OnClickListener myclick = new Button.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      doclick(); 
     } 
    }; 

    public void doclick() { 
     DialogHandler appdialog = new DialogHandler(); 
     appdialog.Confirm(this, "Message title", "Message content", 
       "Cancel", "OK", aproc(), bproc()); 
    } 

    public Runnable aproc(){ 
     return new Runnable() { 
      public void run() { 
       Log.d("Test", "This from A proc"); 
      } 
      }; 
    } 

    public Runnable bproc(){ 
     return new Runnable() { 
      public void run() { 
       Log.d("Test", "This from B proc"); 
      } 
      }; 
    } 


} 
+0

qualcuno ha provato questo, tutte le risposte – Lion789

+0

@ Lion789 Vedere la mia risposta al tuo commento nella mia risposta la vera prova è:. mettere un po 'di codice nel metodo 'onClick()' ** dopo ** invocando 'DoClick()' per verificare la risposta degli utenti alla finestra di dialogo 'DialogHandler' e vedere se l'esecuzione di codice attende la finestra di dialogo per chiudere. penso che non lo farà. – ilomambo

+2

mi piace il suo approccio ed è in esecuzione. ho controllato – Nepster

0

ero anche lottando per utilizzare una finestra di blocco di conferma e alla fine l'ho fatto utilizzando un BlockingQueue:

public static class BlockingConfirmDialog{ 

    private Activity context; 

    BlockingQueue<Boolean> blockingQueue; 

    public BlockingConfirmDialog(Activity activity) { 
     super(); 
     this.context = activity; 
     blockingQueue = new ArrayBlockingQueue<Boolean>(1); 
    } 

    public boolean confirm(final String title, final String message){ 

     context.runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       new AlertDialog.Builder(context) 
       .setTitle(title) 
       .setMessage(message) 
       .setPositiveButton("Ok", new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int which) { 
         blockingQueue.add(true); 
        } 
       }) 
       .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { 
        @Override 
        public void onClick(DialogInterface dialog, int which) { 
         blockingQueue.add(false); 
        } 
       }) 
       .show(); 
      } 
     }); 

     try { 
      return blockingQueue.take(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      return false; 
     } 

    } 
} 
1

trovo che l'utilizzo di jDeferred aiuta nei casi in cui si desidera attendere l'input.

È essenzialmente equivalente all'utilizzo di un'interfaccia, ma invece si creano gestori riusciti e non riusciti. Solo un'alternativa da considerare:

new ConfirmationDialog(mContext) 
     .showConfirmation("Are you sure?", "Yes", "No") 
     .done(new DoneCallback<Void>() { 
      @Override 
      public void onDone(Void aVoid) { 
       .... 
      } 
     }) 
     .fail(new FailCallback<Void>() { 

      @Override 
      public void onFail(Void aVoid) { 
       ... 
      } 
     }); 

Implementazione:

public class ConfirmationDialog { 


    private final Context mContext; 
    private final DeferredObject<Void, Void, Void> mDeferred = new DeferredObject<Void, Void, Void>(); 

    public ConfirmationDialog(Context context) { 
     mContext = context; 
    } 

    public Promise<Void, Void, Void> showConfirmation(String message, String positiveButton, String negativeButton) { 
     AlertDialog dialog = new AlertDialog.Builder(mContext).create(); 
     dialog.setTitle("Alert"); 
     dialog.setMessage(message); 
     dialog.setCancelable(false); 
     dialog.setButton(DialogInterface.BUTTON_POSITIVE, positiveButton, new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int buttonId) { 
       mDeferred.resolve(null); 
      } 
     }); 
     dialog.setButton(DialogInterface.BUTTON_NEGATIVE, negativeButton, new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int buttonId) { 
       mDeferred.reject(null); 
      } 
     }); 
     dialog.setIcon(android.R.drawable.ic_dialog_alert); 
     dialog.show(); 
     return mDeferred.promise(); 
    } 

} 
1

Con Andriod, non è una buona idea per bloccare il filo conduttore aspettando per l'utente di dire 'sì' o 'no' .

Per chiedere una conferma, è possibile definire un metodo che riceve un AsynTask. Il metodo esegue tale attività se l'utente preme il pulsante di conferma.

Ad esempio:

//this method displays a confirm dialog. If 'yes' answer, runs 'yesTask', 
    //if 'no' answer, runs 'noTask' 
    //notice than 'yesTask' and 'noTask' are AysncTask 
    //'noTask' can be null, example: if you want to cancel when 'no answer' 

    public static void confirm(Activity act, String title, String confirmText, 
         String noButtonText, String yesButtonText, 
         final AsyncTask<String, Void, Boolean> yesTask, 
         final AsyncTask<String, Void, Boolean> noTask) { 

    AlertDialog dialog = new AlertDialog.Builder(act).create(); 
    dialog.setTitle(title); 
    dialog.setMessage(confirmText); 
    dialog.setCancelable(false); 
    dialog.setButton(DialogInterface.BUTTON_POSITIVE, yesButtonText, 
     new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int buttonId) { 
       yesTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
      } 
     }); 
    dialog.setButton(DialogInterface.BUTTON_NEGATIVE, noButtonText, 
     new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int buttonId) { 
       if(noTask!=null) { 
        noTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
       } 

      } 
     }); 
    dialog.setIcon(android.R.drawable.ic_dialog_alert); 
    dialog.show(); 
} 

Si può chiamare dalla vostra attività con:

YourTask yourTask = new YourTask(...); 
confirm(YourActivity.this, 
     "Confirm", 
     "Are you sure?", 
     "Cancel", 
     "Continue", 
     yourTask, 
     null); 

YourTask categoria devono estendersi AsyncTask

0

Ho provato tutte le soluzioni e più facile e la più pulita è di gran lunga la prima soluzione con il Runnable, secondo me. Supporta la finestra di dialogo sul listener del pulsante Annulla, OnBAckPressed() e onOptionsItemSelected().

Il codice come descritto se chiamate l'ans_false.run(); quando fai clic su BUTTON_POSITIVE e su ans_true.run(); quando fai clic su BUTTON_NEGATIVE.

Ecco il codice che ho usato per risolvere questo problema:

public class MyDialogs { 

// private constructor 
public Runnable answerTrue = null; 
public Runnable answerFalse = null; 

// Dialog. -------------------------------------------------------------- 

public boolean confirm(Activity act, String Title, String ConfirmText, 
         String noBtn, String yesBtn, Runnable yesProc, Runnable noProc) { 
    answerTrue = yesProc; 
    answerFalse= noProc; 
    AlertDialog.Builder alert = new AlertDialog.Builder(act); 
    alert.setTitle(Title); 
    alert.setMessage(ConfirmText); 
    alert.setCancelable(false); 
    alert.setPositiveButton(R.string.button_positive, new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      answerTrue.run(); 
     } 
    }); 
    alert.setNegativeButton(R.string.button_negative, new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      answerFalse.run(); 
     } 
    }); 
    alert.show().getButton(DialogInterface.BUTTON_NEGATIVE).requestFocus(); 
    return true; 
} 

}

Problemi correlati