Android Back Button и Progress Dialog
У меня есть AsyncTask, который показывает progressDialog во время работы (он вызывает runOnUiThread изнутри doInBackground, чтобы отобразить диалог выполнения).
Пока он работает, я хочу разрешить использование кнопки "Назад" для отмены операции; у кого-то была эта проблема: Кнопка BACK не работает, а progressDialog работает
По какой причине я не могу ответить на этот поток, поэтому нужно начать с другого?! (Еще один вопрос за другой день)
У меня была такая же идея, как у Sandy, но этот код никогда не вызывается, пока показывает прогрессDialog, почему это? Я внедрил его в свой основной класс активности, разве progressDialog временно отвлекает фокус от моего класса?
Ответы
Ответ 1
Сначала вы должны показать свое диалоговое окно от 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
.
Ответ 2
Хорошо, у меня была такая же проблема. Самый простой метод, который работал у меня, - это использовать progressDialog.setCancelable(true)
.. Это объявляет, отменяется ли диалог, нажав на задний ключ. Попробуйте и сообщите мне, работает ли оно для вас или нет. Удачи.
Ответ 3
Это может быть достигнуто с помощью следующего фрагмента кода:
progress.setCancelable(true);
progress.setCanceledOnTouchOutside(false);
прогресс - это объект ProgressDialog...
Это позволит кнопке "Назад" закрыть диалоговое окно, но не позволяет использовать любой сенсорный ввод...
Ответ 4
Я нашел идеальное и простое решение этой проблемы. Для установки KeyListener существует метод ProgressDialog
.
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
Лечение обратной кнопки, как отмены, не является правильным способом.
Отмена также происходит, когда пользователь касается экрана вне диалогового окна.
Вы хотите отличить эти два действия, нет?
Правильный подход заключается в расширении класса 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), снова подчеркивая, что кнопка возврата отличается от простой отмены.
Также это будет эффективно игнорировать любые другие сенсорные входы от пользователя.
Ответ 6
Вот мое решение. Проблема с PD возникает только тогда, когда приложение выходит из кнопки "Назад" (обычно, когда пользователь нажимает ее повторно, и только иногда (не все время) PD вызывается, когда приложение уже уничтожено. Отказ от PD onDestroy
не работает по какой-то причине, и когда я это пробовал, каждое нажатие кнопки "Назад" закроет приложение, хотя для параметра canGoBack()
установлено значение true. Вместо этого я отклоняю PD на goBack
, который является событием, которое вызывает столкновение в первую очередь, и я делаю это прямо перед finish()
. Если приложение выходит на goBack, как правило, там нет проблем в первую очередь.
BTW, "разница" нацелена на то, чтобы позволить пользователю выйти из приложения с быстрым двойным щелчком (400 MS между двумя щелчками мыши), вместо того, чтобы возвращаться со страницы на страницу.
Надеюсь, что это поможет кому-то...
@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();
}
}
Ответ 7
javano... Я протестировал ваш сценарий, используя стандартные методы, asyncTask и ProgressDialog. В моем тесте, когда progressDialog отображается, и я ударяю назад, progressdialog отклоняется и фоновый поток продолжает работать. Я не знаю, почему вам нужно вызвать runOnUiThread.
SO:
показать прогрессDialog в 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
У меня есть код здесь.
Ответ 8
Его очень просто скопировать приведенный ниже код и вставить в задачу Async.
Диалоговое окно 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();
}
Ответ 9
Пожалуйста, следуйте этому, он показывает кнопку отмены только async, и завершение вызовет, нажав кнопку отмены
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();
}