Кнопка возврата Android и диалоговое окно хода выполнения - PullRequest
32 голосов
/ 10 марта 2011

У меня есть AsyncTask , который показывает ProgressDialog во время работы (он вызывает runOnUiThread из doInBackground , чтобы показать диалог прогресса).

Пока он работает, я хочу разрешить использование кнопки «назад» для отмены операции; кто-то еще имел эту проблему: Кнопка BACK не работает, в то время как progressDialog работает

По какой причине я не могу ответить на эту ветку, поэтому мне приходится начинать другую ?! (Еще один вопрос на другой день)

У меня была та же идея, что и у Сэнди, но этот код никогда не вызывается, пока progressDialog показывает, почему это так? Я реализовал это в своем основном классе деятельности. progressDialog временно убирает фокус с моего класса?

Ответы [ 9 ]

44 голосов
/ 10 марта 2011

Сначала вы должны показать свой диалог из OnPreExecute, скрыть его в OnPostExecute и - при необходимости - изменить его, опубликовав прогресс. (см. здесь )

Теперь к вашему вопросу: ProgressDialog.show() может принять OnCancelListener в качестве аргумента. Вы должны предоставить тот, который вызывает cancel() в экземпляре диалогового окна прогресса.

пример:

    @Override
    protected void onPreExecute(){
        _progressDialog = ProgressDialog.show(
                YourActivity.this,
                "Title",
                "Message",
                true,
                true,
                new DialogInterface.OnCancelListener(){
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        YourTask.this.cancel(true);
                        finish();
                    }
                }
        );
    }

, где _progressDialog является ProgressDialog членом YourTask.

Этот класс устарел на уровне API 26. ProgressDialog является модальным диалог, который не позволяет пользователю взаимодействовать с приложением. Вместо использования этого класса, вы должны использовать индикатор прогресса, как ProgressBar, который может быть встроен в пользовательский интерфейс вашего приложения. С другой стороны, Вы можете использовать уведомление, чтобы проинформировать пользователя о ходе выполнения задачи. LINK

14 голосов
/ 03 ноября 2014

Этого можно добиться с помощью следующего фрагмента кода:

progress.setCancelable(true);
progress.setCanceledOnTouchOutside(false);

progress - это объект ProgressDialog ...

Это позволит кнопке «Назад» закрыть диалоговое окно, но предотвратить любое касаниевход для этого ...

13 голосов
/ 01 ноября 2011

Ну, у меня была такая же проблема. Простейший метод, который работал для меня, это использование progressDialog.setCancelable(true) .. Это объявляет, можно ли отменить диалог нажатием клавиши возврата. Попробуйте и дайте мне знать, работает ли он у вас или нет. Удачи

8 голосов
/ 31 июля 2015

Я только что нашел идеальное и простое решение этой проблемы.В ProgressDialog есть метод для установки KeyListener.

progressDialog.setOnKeyListener(new OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
        if(keyCode==KeyEvent.KEYCODE_BACK && !event.isCanceled()) {
            if(progressDialog.isShowing()) {
                //your logic here for back button pressed event
            } 
            return true;
        }
        return false;
    }
});

Он отлично работает с setCancelable(false).Я также проверяю на event.isCanceled(), потому что без этого я получал два события.Я проверил это на устройстве Lollipop с аппаратными ключами и без них.

5 голосов
/ 28 февраля 2013

Неправильное обращение с кнопкой возврата как отменой.
Отмена также происходит, когда пользователь касается экрана за пределами диалогового окна. Вы хотите различать эти два действия, нет?

Правильный подход заключается в расширении класса ProgressDialog и переопределении метода onBackPressed.

private class SubProgressDialog extends ProgressDialog {
    public SubProgressDialog(Context context) {
        super(context);
    }
    @Override
    public void onBackPressed() {
        /** dismiss the progress bar and clean up here **/
    }
}


public void displayProgressBar(){
    progressBar = new SubProgressDialog(this);
    progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressBar.setCancelable(false);
    progressBar.setMessage(getString(R.string.authorizing));        
    progressBar.show();   
    new Thread(new Runnable() {
      public void run() {
      }
       }).start();     

}

Обратите внимание на setCancelable (false), еще раз подчеркнув, что кнопка возврата отличается от простой отмены.
Также это эффективно игнорирует любые другие сенсорные вводы от пользователя.

3 голосов
/ 20 ноября 2014

Вот мое решение для этого.Проблема с ПД возникает только тогда, когда приложение выходит из кнопки «назад» (обычно, когда пользователь нажимает на нее несколько раз, и только иногда (не всегда) ПД вызывается, когда приложение уже уничтожено. Увольнение ПД onDestroy не работаетпо какой-то причине, и когда я попробовал это, каждое нажатие кнопки Назад закрывало приложение, хотя canGoBack() было установлено в значение true. Вместо этого я отклонял PD на goBack, что в первую очередь является событием, которое вызывает столкновение,и я делаю это прямо перед finish(). Если приложение обычно выходит из goBack, то, во-первых, проблем нет.

Кстати, «разница» предназначена для того, чтобы позволить пользователю быстро выйти из приложениящелкните (400 мс между двумя щелчками) вместо перехода от страницы к странице.

Надеюсь, это кому-нибудь поможет ...

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (event.getAction() == KeyEvent.ACTION_DOWN) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_BACK:
            difference = System.currentTimeMillis() - startTime;
            if (wView.canGoBack() && difference > 400) {
                wView.goBack();
            } else {
                dismissProgressDialog();
                finish();
            }
            startTime = System.currentTimeMillis();
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}


private void dismissProgressDialog() {
   if (progressDialog != null && progressDialog.isShowing()) {
        progressDialog.dismiss();
   }
}
2 голосов
/ 10 марта 2011

javano ... Я протестировал ваш сценарий, используя стандартные методы, asyncTask и ProgressDialog. В моем тесте, когда ProgressDialog показывает, и я наносил ответный удар, ProgressDialog отклоняется, и фоновый поток продолжает работать. Я не знаю, зачем вам нужно вызывать runOnUiThread.

SO:

показать диалоги выполнения в onPreExecute поместите долгосрочную задачу в doInBackground отклонить progressDialog в onPostExecute передать входные параметры в вашу долгосрочную задачу как:

new MyAsynch().execute(password,inString);

cancel () asynchTask и progressDialog в onPause

protected void onPause() {
    super.onPause();
    if (asynch != null) {asynch.cancel(true);}
    if (progress != null){progress.cancel();}
}

JAL

У меня есть код здесь .

1 голос
/ 18 апреля 2015

Очень просто скопировать приведенный ниже код и вставить в асинхронную задачу.

Диалог ProgressDialog;

@Override
protected void onPreExecute() {

    dialog = new ProgressDialog(MainActivity.this) {
        @Override
        public void onBackPressed() {
            dialog.cancel();
            dialog.dismiss();
        }
    };
    // dialog.setTitle("file is..");//its optional If u want set title in progress
    // bar
    dialog.setMessage("Loading file....");
    dialog.setCancelable(false);

    dialog.show();

}
0 голосов
/ 31 декабря 2014

Пожалуйста, следуйте инструкциям, она показывает только асинхронную кнопку отмены и завершит вызов, нажав кнопку отмены

protected void onPreExecute() {


        dialogx.setMessage("Loading... Please Wait...");
        dialogx.setCancelable(false);
        dialogx.setButton(DialogInterface.BUTTON_NEGATIVE,
                "Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

                dialogx.dismiss();
                GetDataTask.this.cancel(true);
                finish();
            }
        });
        dialogx.show();


    }
...