Dialogs / AlertDialogs: как «заблокировать выполнение», когда диалог открыт (в стиле .NET) - PullRequest
68 голосов
/ 08 января 2010

Исходя из .NET-среды, я сейчас пытаюсь понять, как работают диалоги в Android.

В .NET при вызове MessageBox.Show(...), который создает и показывает всплывающее диалоговое окно. В вызове Show я могу указать, какие кнопки должны быть доступны во всплывающем окне, например:

DialogResult myDialogResult = MessageBox.Show("My text here", "My caption here", MessageBoxButtons.YesNoCancel);

Как видите, вызов Show возвращает DialogResult при нажатии кнопки во всплывающем окне, сообщая мне, какая кнопка была нажата. Обратите внимание, что в .NET выполнение останавливается в строке, где выполняется вызов Show(...), поэтому он может возвращать значение при нажатии кнопки.

Если в приведенном выше примере нажать «Нет», myDialogResult будет равен

myDialogResult == DialogResult.No

Поскольку я считаю, что .NET-способ использования / создания всплывающих окон очень прост и интуитивно понятен, я бы хотел, чтобы этот способ также создавал всплывающие окна в Android.

Итак, вопрос в том, знает ли кто-нибудь, как «остановить выполнение», как с помощью MessageBox.Show, и затем возвращать значение при каждом нажатии кнопки (и диалог исчезает)?

Редактировать 1

Чтобы быть немного яснее:

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

Вот почему я не могу использовать то, что предлагают Эрих и Алекс, так как написание кода в методах onClick, как предлагается ниже, не будет работать. Причина в том, что я не могу продолжать «нормальное исполнение». Позвольте мне привести пример:

Позвольте мне привести пример:

int nextStep = 0; // this variable will not be reached from within the onClick-methods

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Hello!")
       .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                nextStep = 1; // *** COMPILER ERROR!! ***
            }
        })
        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                nextStep = 2; // *** COMPILER ERROR!! ***
            }
        })
        .create().show();

if (nextStep == 1)
{
    // then do some damage
}
else if (nextStep == 2
    // dont do damage

Если бы я хотел, чтобы выполнение зависело от выбора во всплывающем окне, я бы как-то должен был сделать все переменные в «нормальном исполнении» (в данном случае nextStep) доступными в методах onClick, и это звучит как ад для меня.

Редактировать 2

Другим очевидным примером будет всплывающее окно с вопросом «Хотите продолжить» с параметрами «Да» и «Нет» .

Если пользователь нажимает «Да», весь метод должен быть прерван, в противном случае он должен продолжить выполнение. Как вы решаете это красиво?

Ответы [ 18 ]

1 голос
/ 26 января 2014

Перезапись:

Существуют радикальные различия между мобильной и настольной средой, а также между тем, как приложения разрабатывались несколько лет назад и сегодня:

а) мобильные устройства должны сохранять энергию. Часть ценности, которую они предлагают. Так что вам нужно экономить ресурсы. Нити являются дорогим ресурсом. Остановка прогресса потока является недопустимой тратой этого ресурса.

б) В наше время пользователь гораздо более требователен. Чтобы помочь им, мы полагаем, что он заслуживает полноценного процессора и минимальных затрат энергии. Его приложение не одиноко на устройстве, есть неизвестное количество других приложений, работающих одновременно, и ваше приложение не обязательно является самым срочным.

в) блокировки на системном уровне не являются опцией: мобильное устройство работает с рядом событий и служб в фоновом режиме, и оно не подходит для любого из них, который может быть заблокирован приложением.

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

Исходя из вышеизложенного, ответ на предложенный вопрос таков:

  • Существует жизнеспособный способ создания диалога, который блокирует основной поток до получения ответа от пользователя?

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

  • Есть ли способ заблокировать всю систему с помощью диалога?

Нет. Это строго запрещено на платформе. Ни одно приложение не может вмешиваться в работу системы или других приложений.

  • Мне нужно провести рефакторинг своего приложения или переосмыслить свой способ программирования в соответствии с архитектурой мобильной системы Android.

Да. Включая этот аспект.

0 голосов
/ 20 декабря 2013
UserSelect =null

AlertDialog.Builder builder = new Builder(ImonaAndroidApp.LoginScreen);
            builder.setMessage("you message");
            builder.setPositiveButton("OK", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    UserSelect = true ;

                }
            });

            builder.setNegativeButton("Cancel", new OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    UserSelect = false ;

                }
            });
           // in UI thread
        builder.show();             
        // wait until the user select
            while(UserSelect ==null);
0 голосов
/ 11 мая 2012

Я новичок в мире Android / Java и с удивлением обнаружил здесь (если я не понимаю, что я читаю), что модальные диалоги не работают. По некоторым неясным для меня причинам в данный момент я получил этот «ShowMessage» эквивалент с кнопкой «ok», которая очень модально работает на моем планшете.

Из моего модуля TDialogs.java:

class DialogMes 
{

  AlertDialog alertDialog ;
  private final Message NO_HANDLER = null;
  public DialogMes(Activity parent,String aTitle, String mes)
  {
    alertDialog = new AlertDialog.Builder(parent).create();
    alertDialog.setTitle(aTitle);    
    alertDialog.setMessage(mes) ;  
    alertDialog.setButton("OK",NO_HANDLER) ;    
    alertDialog.show() ; 
  } 
}

Вот часть кода теста:

public class TestDialogsActivity extends Activity implements DlgConfirmEvent
{

   @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Button btShowMessage = (Button) findViewById(R.id.btShowMessage);
    btShowMessage.setOnClickListener(new View.OnClickListener() {
      public void onClick(View view) 
      {
        DialogMes dlgMes = new DialogMes( TestDialogsActivity.this,"Message","life is good") ;                
      }  
    }); 

Я также реализовал модальное диалоговое окно «Да / Нет», следуя интерфейсному подходу, предложенному выше JohnnyBeGood, и он тоже работает довольно хорошо.

Исправление:

Мой ответ не имеет отношения к вопросу, который я неправильно понял. По какой-то причине я интерпретировал г-на Ромена Гая «вы не хотите этого делать» как модальные диалоги «нет». Я должен был прочитать: «Вы не хотите делать это ... таким образом».

Прошу прощения.

0 голосов
/ 20 января 2011

Попробуйте это в теме (не в теме):

final CountDownLatch latch = new CountDownLatch(1);
handler.post(new Runnable() {
  @Override
  public void run() {
    OnClickListener okListener = new OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
      dialog.dismiss();
      latch.countDown();
    }
  };

  AlertDialog dialog = new AlertDialog.Builder(context).setTitle(title)
    .setMessage(msg).setPositiveButton("OK", okListener).create();
  dialog.show();
}
});
try {
  latch.await();
} catch (InterruptedException e) {
  e.printStackTrace();
}
0 голосов
/ 18 ноября 2010

просто чтобы ответить на ваш вопрос ... кстати, я извиняюсь, что опоздал на 9 месяцев: D ... есть "обходной путь" 4 такого рода проблем т.е.

new AlertDialog.Builder(some_class.this).setTitle("bla").setMessage("bla bla").show();
wait();

просто добавьте wait ();

и они в OnClickListener снова запускают класс с notify () примерно так

@Override
    public void onClick(DialogInterface dialog, int item) {
        Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_LONG).show();
        **notify**();
        dialog.cancel();
    }

тот же обходной путь - 4 тоста и другие асинхронные вызовы в Android

0 голосов
/ 08 января 2010

Это самый простой способ:

new AlertDialog.Builder(this).setTitle("title").setMessage("message").create().show();
0 голосов
/ 16 апреля 2014

Я использую Xamarin.Android (MonoDroid), и у меня есть требования для разработки окна подтверждения блокировки пользовательского интерфейса. Я не собираюсь спорить с клиентом, потому что вижу веские причины, почему они этого хотят ( подробности здесь ), поэтому мне нужно это реализовать. Я пробовал @Daniel и @MindSpiker выше, но они не работали на MonoForAndroid, в момент отправки сообщения между потоками приложение зависало. Я предполагаю, что это как-то связано с картированием Xamarin.

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

// (since the controllers code is shared cross-platforms)
protected void RunConfirmAction(Action runnableAction)
{
    if (runnableAction != null)
    {
        if (Core.Platform.IsAndroid)
        {
            var confirmThread = new Thread(() => runnableAction());
            confirmThread.Start();
        }
        else
        {
            runnableAction();
        }
    }
}

// The call to the logout method has now changed like this:
RunConfirmAction(Logout);

// the implemtation of the MessageBox waiting is like this:
public DialogResult MessageBoxShow(string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
{
    if (_CurrentContext != null && _CurrentContext.Screen != null && MainForm.MainActivity != null)
    {
        Action<bool> callback = OnConfirmCallBack;
        _IsCurrentlyInConfirmProcess = true;
        Action messageBoxDelegate = () => MessageBox.Show(((Activity)MainForm.MainActivity), callback, message, caption, buttons);
        RunOnMainUiThread(messageBoxDelegate);
        while (_IsCurrentlyInConfirmProcess)
        {
            Thread.Sleep(1000);
        }               
    }
    else
    {
        LogHandler.LogError("Trying to display a Message box with no activity in the CurrentContext. Message was: " + message);
    }
    return _ConfirmBoxResult ? DialogResult.OK : DialogResult.No;

}

private void OnConfirmCallBack(bool confirmResult)
{
    _ConfirmBoxResult = confirmResult;
    _IsCurrentlyInConfirmProcess = false;
}

private bool _ConfirmBoxResult = false;
private bool _IsCurrentlyInConfirmProcess = false;

Полную информацию о том, как это сделать, можно найти в моем блоге здесь

0 голосов
/ 08 января 2010

вы устанавливаете на слушателей кнопки onclick для вас. распусти диалог и сделай свое действие. Не нужно ничего останавливать

protected Dialog onCreateDialog(int id) {
  return new AlertDialog.Builder(this).setTitle(R.string.no_connection).setIcon(android.R.drawable.ic_dialog_alert).setView(textEntryView).setPositiveButton(R.string.exit, new DialogInterface.OnClickListener() 
{

   public void onClick(DialogInterface dialog, int whichButton) {

  // Here goes what you want to do
  }

})
}

для вызова - ex - showDialog (DIALOG_ERROR_PREF);

Подробнее http://developer.android.com/guide/topics/ui/dialogs.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...