Диалоговое окно подтверждения Android возвращает истину или ложь

Кажется, нет простого способа получить диалоговое окно с предупреждением, чтобы вернуть простое значение.
Этот код не работает (переменная answer не может быть установлена ​​из внутри слушателя, на самом деле он даже не компилируется)

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

ПРИМЕЧАНИЕ. Важно, чтобы метод был самодостаточным, т. Е. Не зависел от переменных или внешних по отношению к нему конструкций. Просто позвоните и получите ответ, правда или ложь.

Так что делать? Это простое желание вернуть true или false кажется гораздо более сложным, чем оно того заслуживает.

Также метод setButton имеет вид:

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

Но непонятно, как им пользоваться, куда отправляется сообщение, кому, какой обработчик используется?


person ilomambo    schedule 26.05.2012    source источник


Ответы (8)


У меня есть аналогичная проблема на этом форуме, но, наконец, я получил свой ответ. Моя проблема в этом сообщении заключается в том, как создать отдельный класс диалогового окна подтверждения, к которому может получить доступ другой класс или действие, поэтому с этим классом диалогового окна подтверждения нам не нужно писать длинное кодирование.

вот мой ответ.

Сначала вы должны создать 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;
    }
}

И это пример для вызова его в другом классе

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


}
person AsepRoro    schedule 19.11.2012
comment
@ Lion789 См. Мой ответ на ваш комментарий в моем собственном ответе. Настоящая проверка здесь: поместите код в onClick() метод после вызова doClick(), чтобы проверить реакцию пользователя на DialogHandler диалоговое окно и посмотреть, ожидает ли выполнение этого кода закрытия диалогового окна. Думаю, не будет. - person ilomambo; 27.02.2014
comment
Мне нравится ваш подход, и он работает. Я это проверил. - person AndroidGeek; 08.07.2014
comment
@Roro Отличная работа. Оно работает. Это должен быть принятый ответ - person denizen; 22.09.2016
comment
@AsepRoro Хорошая логика .. Хорошо работает. Это действительно должен быть принятый ответ. - person Neil B; 06.09.2018

Что ж, я собирался сказать, что очень доволен собой, потому что я сам нашел простой ответ!
Но правда в том, что хотя я нахожу способ вернуть значение (которое я показываю ниже). Это бесполезно.

Настоящая проблема в том, что мне нужен синхронный диалог, диалоговое окно, которое ожидает ответа пользователя, прежде чем возобновить ваш код после dialog.show().
В Android нет такого зверя. Все диалоги асинхронны, поэтому dialog.show() только отправляет диалог в некоторую очередь (я думаю) и продолжается. Таким образом, вы не получите ответ вовремя.

При всей своей ценности (ничего) ниже вы найдете, как установить значение внутри метода, который строит диалог. Возможно, есть другие варианты использования этого метода, не связанные с жизненным циклом диалога.




Чтобы дать некоторую связанную информацию, я скажу, что если вы замените

boolean answer;

с участием

final boolean answer;

можно получить доступ к переменной из прослушивателя, но невозможно присвоить ей новое значение, поскольку оно было объявлено как final.

Вот и весь трюк.
Определите переменную как:

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

Некоторые из вас уже понимают, почему это сработает. Последняя переменная здесь не является единственным элементом логического массива, это сам массив.
Итак, теперь вы можете присвоить элемент массива [0] по своему усмотрению.

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

И, наконец, вы можете вернуть его из своего метода.

person ilomambo    schedule 26.05.2012
comment
Вы когда-нибудь находили лучшее решение? - person Lion789; 10.02.2014
comment
@ Lion789 Как я уже сказал, это не совсем решение, и я объяснил, почему с текущей ОС Android не может быть никаких проблем. Так что короче лучшего решения не нашел. Согласно Android, вы должны поместить свой код в прослушиватель onClick () для диалога. Это единственный способ выполнить его после закрытия диалогового окна. - person ilomambo; 10.02.2014
comment
iLomambo Вы пробовали один наверху с вызовом Runnable? - person Lion789; 27.02.2014
comment
С тех пор я перешел в другие проекты, поэтому не пробовал. Но если вы понимаете мой ответ, то довольно очевидно, как он будет себя вести. Из-за асинхронного символа Android в тот момент, когда вы вызываете show(), отображается диалоговое окно и код продолжается, он не ждет, пока пользователь нажмет OK - person ilomambo; 27.02.2014
comment
правильно, но если в коде больше ничего нет, кроме, например, onClick (dialog (proca (), procb ()), экран изменится только после выбора, независимо от async, потому что в procA я говорю ему, что делать, и это не будет выполнено если в диалоговом окне не указано, что нужно запустить - person Lion789; 27.02.2014

Что вы можете сделать, так это создать прослушиватель для вашего диалогового окна предупреждений, который прослушивает действие AlertDialogs с помощью интерфейса.

Создайте интерфейс.

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;

    }
}

Теперь в вашем классе просто реализуйте интерфейс, который вы создали с помощью implements MyInterface.DialogReturn

затем вы можете установить Listener и заставить его работать, как показано ниже,

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
    }
}
person Lalit Poptani    schedule 26.05.2012
comment
Я предполагаю, что ваше предложение работает. Но какой сложный способ добиться простой вещи! Вы так не думаете? - person ilomambo; 26.05.2012
comment
Да, правда, но это не так уж сложно, если мы однажды поймем это и заставим работать. - person Lalit Poptani; 26.05.2012
comment
@ilomambo ‹unsolicitedEditorial› Добро пожаловать в Android! Если на то пошло, добро пожаловать на Java. ‹/UnsolicitedEditorial› - person Peter Ajtai; 26.09.2013

Я считаю, что использование jDeferred помогает в тех случаях, когда вы хотите дождаться ввода.

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

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

Реализация:

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

}
person Peter Ajtai    schedule 26.09.2013

С Andriod не рекомендуется блокировать запущенный поток, ожидая, пока пользователь скажет «да» или «нет».

Чтобы запросить подтверждение, вы можете определить метод, который получает AsynTask. Метод выполняет эту задачу, если пользователь нажимает кнопку подтверждения.

Например:

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

Вы можете вызвать его из своей деятельности с помощью:

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

YourTask класс должен расширяться AsyncTask

person robcalvo    schedule 18.04.2015

Объявите поле «ответ» в своей деятельности и установите для него значение. Поля класса видны внутренним классам, так что вы можете это сделать.

person Vladimir Ivanov    schedule 26.05.2012
comment
Да .. Я не упоминал об этом, но мне нужно, чтобы метод не зависел от класса, в котором он определен. Нельзя использовать переменную класса. Я обновлю вопрос, чтобы было понятнее. - person ilomambo; 26.05.2012

Я также изо всех сил пытался использовать диалоговое окно подтверждения блокировки, и я, наконец, сделал это с помощью 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;
        }

    }
}
person Guillaume    schedule 05.08.2013

Я перепробовал все решения, и, на мой взгляд, самое простое и чистое - это, безусловно, первое решение с Runnable. Он поддерживает диалог в прослушивателе кнопки Отмена, OnBAckPressed () и onOptionsItemSelected ().

Однако описанный код вызывает ans_false.run (); при нажатии кнопок BUTTON_POSITIVE и ans_true.run (); при нажатии кнопки BUTTON_NEGATIVE.

Вот код, который я использовал для решения этой проблемы:

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

}

person mmarin1m    schedule 16.06.2017