personalizado - tipos de dialogos en android studio
El diĆ”logo de confirmaciĆ³n de Android devuelve verdadero o falso (8)
Bueno, iba a decir que estoy muy contento conmigo mismo porque encontré una respuesta simple, ¡todo solo!
Pero la verdad es que aunque encuentro una forma de devolver un valor (que muestro más abajo). No sirve de nada
El verdadero problema es que quería un diálogo sincrónico, un diálogo que espera que el usuario responda antes de reanudar el código después de dialog.show()
.
No existe tal bestia en Android . Todos los diálogos son asincrónicos, por lo que dialog.show()
solo publica el diálogo en alguna cola (creo) y continúa. Por lo tanto, no obtienes tu respuesta a tiempo.
A pesar de su valor (nada) a continuación, encontrará cómo establecer un valor dentro del método que crea el diálogo. Tal vez haya otros usos para esta técnica, no relacionados con el ciclo de vida del diálogo.
Para dar algo de información relacionada, diré que si reemplazas
boolean answer;
con
final boolean answer;
es posible acceder a la variable desde el oyente, pero no es posible asignarle un nuevo valor, ya que se declaró como final .
Aquí viene el truco.
Defina la variable como:
final boolean[] answer = new boolean[1];
Algunos de ustedes ya ven por qué esto funcionará. La variable final aquí no es el único elemento de la matriz booleana, es la matriz en sí misma.
Entonces ahora puede asignar el elemento de matriz [0] como desee.
dialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int buttonId) {
answer[0] = true;
}
});
. . .
return answer[0];
Y finalmente puedes devolverlo desde tu método.
Parece que no hay una forma fácil de obtener un diálogo de alerta para devolver un valor simple.
Este código no funciona (la variable de respuesta no se puede establecer desde dentro del oyente, de hecho ni siquiera se compila)
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: Es importante que el método sea independiente, es decir, que no dependa de variables o construcciones externas a él. Solo llámalo y obtén tu respuesta, verdadera o falsa.
¿Entonces lo que hay que hacer? Este simple deseo de regresar verdadero o falso parece ser mucho más complicado de lo que merece.
Además, el método setButton tiene la forma:
dialog.setButton(int buttonId, String buttonText, Message msg)
Pero no está claro cómo usarlo, ¿a dónde se envía la correspondencia, a quién, qué controlador se utiliza?
Declare un campo ''respuesta'' en su actividad y establezca un valor para ella. Los campos de una clase son visibles para las clases internas, por lo que puede hacer eso.
Lo que puede hacer es crear un Oyente para su Diálogo de Alerta que escuche la acción AlertDialogs utilizando una Interfaz.
Crea una interfaz.
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;
}
}
Ahora, en su clase simplemente implemente la Interfaz que creó usando implements MyInterface.DialogReturn
luego puede configurar el Listener y hacer que funcione como se muestra a continuación,
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
}
}
También estaba luchando por usar un diálogo de confirmación de bloqueo y finalmente lo hice usando una 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;
}
}
}
Encuentro que el uso de jDeferred ayuda en los casos en que desea esperar la entrada.
Es esencialmente equivalente a usar una interfaz, pero en su lugar crea manejadores de hechos y fallos. Solo una alternativa a considerar:
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) {
...
}
});
Implementación:
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();
}
}
Con Andriod, no es una buena idea bloquear el hilo en ejecución esperando que el usuario diga ''sí'' o ''no''.
Para solicitar una confirmación, puede definir un método que reciba una AsynTask. El método ejecuta esa tarea si el usuario presiona el botón confirmar.
Por ejemplo:
//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();
}
Puedes llamarlo desde tu actividad con:
YourTask yourTask = new YourTask( ... );
confirm( YourActivity.this,
"Confirm",
"Are you sure?",
"Cancel",
"Continue",
yourTask,
null);
YourTask
clase YourTask
debe extender AsyncTask
Tengo un problema similar en este foro, pero finalmente recibo mi respuesta. mi problema en esa publicación es cómo crear una clase de diálogo de confirmación separada que pueda acceder por otra clase o actividad, de modo que con esa clase de diálogo de confirmación no es necesario escribir una codificación larga.
esta es mi respuesta.
Primero debes crear 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;
}
}
Y este es un ejemplo para llamarlo en otra clase
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");
}
};
}
}
He probado todas las soluciones y la más fácil y limpia es, de lejos, la primera solución con Runnable, en mi opinión. Admite el diálogo en el oyente del botón Cancelar, OnBackPressed () y onOptionsItemSelected ().
Sin embargo, el código como se describe llama al ans_false.run (); al hacer clic en BUTTON_POSITIVE y en ans_true.run (); al hacer clic en BUTTON_NEGATIVE.
Aquí está el código que utilicé para solucionar ese 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;
}
}