2012-05-26 5 views
9

Es scheint, es ist keine einfache Möglichkeit ist es, einen Benachrichtigungsdialog zurückzukehren einen einfachen Wert zu erhalten.
Dieser Code funktioniert nicht (die Antwort Variable nicht von innerhalb des Zuhörers eingestellt werden können, in der Tat ist es nicht einmal kompilieren)Android Bestätigungsdialog Rückkehr wahr oder falsch

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; 
} 

HINWEIS: Es ist wichtig, dass das Verfahren selbst ist enthalten, dh es hängt nicht von Variablen oder Konstrukten außerhalb davon ab. Rufen Sie es einfach an und erhalten Sie Ihre Antwort, wahr oder falsch.

Also, was zu tun ist? Dieser einfache Wunsch der Rückkehr wahr oder falsch scheint viel komplizierter zu sein, als es verdient.

Auch hat die setButton Methode, um die Form:

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

Aber es ist nicht klar, wie es zu benutzen, wo die meesage geschickt, an wen, welche Handler verwendet wird?

Antwort

9

Nun, ich war Ich werde sagen, dass ich sehr zufrieden mit mir selbst bin, weil ich eine einfache Antwort gefunden habe, ganz allein!
Aber die Wahrheit ist, dass obwohl ich einen Weg finde, einen Wert (der ich unten zeige) zurückzugeben. Es nützt nichts.

Das eigentliche Problem ist, ich wollte einen synchronen Dialog, ein Dialogfeld, das darauf wartet, dass der Benutzer antwortet, bevor Sie Ihren Code nach dialog.show() fortsetzen.
Es gibt keine solche Tiere in Android. Alle Dialoge sind asynchron, so dass dialog.show() den Dialog nur in einer Warteschlange (denke ich) veröffentlicht und fortfährt. So bekommst du deine Antwort nicht rechtzeitig.

Für alle seine Wert (nichts) unten finden Sie, wie Sie einen Wert innerhalb der Methode, die den Dialog erstellt. Vielleicht gibt es andere Anwendungen für diese Technik, die nicht mit dem Dialoglebenszyklus zusammenhängen.




einige relevante Informationen zu geben, ich werde sagen, dass, wenn Sie

boolean answer; 

mit

final boolean answer; 

ersetzen es möglich ist, die Variable für den Zugriff von innerhalb des Listeners, aber es ist nicht möglich, ihm einen neuen Wert zuzuweisen, seit es als endgültig deklariert wurde.

Hier kommt der Trick.
Definieren Sie die Variable wie:

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

Einige von euch schon sehen, warum dies funktioniert. Die letzte Variable ist nicht das einzelne Element des booleschen Arrays, sondern das Array selbst.
Nun können Sie das Array-Element [0] wie gewünscht zuweisen.

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

Und schließlich können Sie es von Ihrer Methode zurückgeben.

+0

Sie haben jemals eine bessere Lösung gefunden? – Lion789

+1

@ Lion789 Wie ich schon sagte, ist das nicht wirklich eine Lösung und ich erklärte, warum es mit dem aktuellen Android OS keine Lösung geben kann. Kurz gesagt, ich habe keine bessere Lösung gefunden. Laut Android sollten Sie Ihren Code in den onClick() - Listener für den Dialog einfügen. Das ist die einzige Möglichkeit, es auszuführen, nachdem Sie den Dialog geschlossen haben. – ilomambo

+0

iLomambo Haben Sie versucht, die oben mit dem Aufruf Runnable – Lion789

0

ein Feld ‚Antwort‘ in Ihrer Tätigkeit erklären und einen Wert setzen. Felder einer Klasse sind für innere Klassen sichtbar, also können Sie das tun.

+0

Ja .. Ich habe nicht erwähnt, aber ich brauche, um die Methode zu sein, unabhängig von der Klasse sie definiert ist in Eine Klassenvariable kann nicht verwendet werden. Ich werde die Frage aktualisieren, um sie klarer zu machen. – ilomambo

3

Was können Sie tun, ist ein Listener für Ihre Alert-Dialog erstellen, die auf AlertDialogs Aktion hört eine Schnittstelle.

Erstellen Sie eine Schnittstelle.

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; 

    } 
} 

nun in der Klasse nur die Schnittstelle implementieren, die Sie implements MyInterface.DialogReturn

mit erstellt, dann können Sie den Listener gesetzt und bekommen es als Show arbeiten unten,

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

Ich gehe davon aus, dass dein Vorschlag funktioniert. Aber was für ein komplizierter Weg, um eine einfache Sache zu erreichen! Denkst du nicht? – ilomambo

+0

Ja, wahr, aber das ist nicht so kompliziert, wenn wir es einmal verstehen und es funktioniert. –

+2

@ilomambo Willkommen bei Android! Willkommen bei Java.

14

Ich habe Post ähnliches Problem in diesem Forum, aber schließlich bekomme ich meine Antwort. mein Problem in diesem Beitrag ist, wie separate Confirm-Dialog-Klasse erstellen, die durch andere Klasse oder Aktivität zugreifen können, so dass mit dieser Confirm-Dialog-Klasse müssen wir nicht lange Codierung schreiben.

Hier ist meine Antwort.

Zuerst müssen Sie 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; 
    } 
} 

erstellen Und das ist es beispielsweise in einer anderen Klasse zu nennen

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

Hat jemand versucht dies, irgendwelche Antworten? – Lion789

+0

@ Lion789 Siehe meine Antwort auf Ihren Kommentar in meiner eigenen Antwort.Der echte Test hier ist: Legen Sie einige Code in der 'onClick()' Methode ** nach ** Aufruf von 'doClick()', um die Benutzerantwort auf den 'DialogHandler'-Dialog zu prüfen und zu sehen, ob diese Codeausführung auf das Schließen des Dialogs wartet. Ich denke, es wird nicht. – ilomambo

+2

Ich mag Ihren Ansatz und es läuft überprüft es. – Nepster

0

Ich war auch einen Sperrbestätigungsdialog zu verwenden, zu kämpfen und ich es endlich tat mit einem Blocking:

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

ich, dass die Verwendung finden jDeferred hilft in Fällen, in denen Sie auf Eingaben warten möchten.

Es entspricht im Wesentlichen der Verwendung einer Schnittstelle, aber stattdessen erstellen Sie Done- und Fail-Handler. Nur eine Alternative zu betrachten:

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) { 
       ... 
      } 
     }); 

Umsetzung:

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

Mit Andriod, es ist keine gute Idee, den laufenden Faden durch das Warten auf den Benutzer zu sagen ‚Ja‘ oder ‚Nein‘ zu blockieren .

Um nach einer Bestätigung zu fragen, können Sie eine Methode definieren, die eine AsynTask empfängt. Die Methode führt diese Aufgabe aus, wenn der Benutzer die Bestätigungstaste drückt.

Zum Beispiel:

//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(); 
} 

Sie können damit aus Ihrer Tätigkeit nennen:

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

YourTask Klasse erweitern müssen AsyncTask

0

ich alle Lösungen und einfacher versucht haben und sauberste ist meiner Meinung nach bei weitem die erste Lösung mit dem Runnable. Es unterstützt den Dialog auf den Listener "Abbrechen", OnBackPressed() und onOptionsItemSelected().

Der Code wie beschrieben, obwohl ruft die ans_false.run(); wenn Sie auf BUTTON_POSITIVE und ans_true.run() klicken; wenn Sie auf BUTTON_NEGATIV klicken. Hier

ist der Code, den ich verwenden, um dieses Problem zu beheben:

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; 
} 

}