web-dev-qa-db-ja.com

Android戻るボタンと進行状況ダイアログ

動作中にprogressDialogを表示するAsyncTaskがあります(進行ダイアログを表示するためにdoInBackgroundからrunOnUiThreadを呼び出します)。

実行中に、戻るボタンを使用して操作をキャンセルできるようにします。他の誰かがこの問題を抱えていました: progressDialogの実行中に[戻る]ボタンが機能しない

そのスレッドに返信できない理由が何であれ、別のスレッドを開始する必要がありますか?! (別の日の別の質問)

私はSandyと同じ考えを持っていましたが、progressDialogが表示されている間、このコードが呼び出されることはありません。これはなぜですか?メインアクティビティクラス内に実装しましたが、progressDialogは一時的にクラスからフォアグラウンドフォーカスを取り除きますか?

32
jwbensley

まず、ダイアログを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();
                    }
                }
        );
    }

どこ _progressDialogProgressDialogYourTaskメンバーです。

このクラスはAPIレベル26で廃止されました。ProgressDialogはモーダルダイアログであり、ユーザーがアプリと対話することを防ぎます。このクラスを使用する代わりに、アプリのUIに埋め込むことができるProgressBarなどの進行状況インジケーターを使用する必要があります。または、通知を使用して、ユーザーにタスクの進行状況を通知できます。 [〜#〜] link [〜#〜]

44
user634618

これは、次のコードフラグメントによって実現できます。

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

progressはProgressDialogオブジェクトです...

これにより、戻るボタンでダイアログを閉じることができますが、タッチ入力を行うことはできません...

14
Jahid

まあ、私は同じ問題を抱えていた。私のために働いた最も簡単な方法は、progressDialog.setCancelable(true)。を使用することです。これは、バックキーを押すことでダイアログがキャンセル可能かどうかを宣言します。幸運を

13
Farhan

この問題に対する完璧で最も簡単な解決策を見つけました。 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()もチェックしています。これがないと、2つのイベントが発生していました。ハードウェアキーの有無にかかわらず、Lollipopデバイスでこれをテストしました。

8
Ashish Tanna

戻るボタンをキャンセルのように扱うのは正しい方法ではありません。
キャンセルは、ユーザーがダイアログボックスの外側の画面にタッチしたときにも発生します。これら2つのアクションを区別したいですか?

正しいアプローチは、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)に注意してください。ここでも、戻るボタンは単純なキャンセルとは異なることを強調しています。
また、これはユーザーからの他のタッチ入力を効果的に無視します。

5
Kevin

これが私の解決策です。 PDの問題は、アプリが戻るボタンで終了する場合にのみ発生します(通常は、ユーザーが繰り返し押したときに、常に(常にではない)PD PD onDestroyを閉じることは何らかの理由で機能せず、試してみると、[戻る]ボタンを押すたびにアプリが閉じられますが、 canGoBack()はtrueに設定されていました。代わりにPD on goBackを破棄します。これは、最初に衝突を引き起こすイベントです。 finish()の直前アプリがgoBackで正常に終了した場合、そもそも問題はありません。

ちなみに、「違い」は、ユーザーがページからページに戻るのではなく、高速ダブルクリック(2回のクリックで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();
   }
}
3
ofermc

javano ... asyncTaskとProgressDialogの標準的な手法を使用して、シナリオをテストしました。私のテストでは、progressDialogが表示されているときにヒットすると、progressdialogは閉じられ、バックグラウンドスレッドの実行が継続されます。 runOnUiThreadを呼び出す必要がある理由がわかりません。

そう:

onPreExecuteにprogressDialogを表示し、doInBackgroundに長時間実行タスクを配置します。onPostExecuteにprogressDialogを閉じます。次のように、入力パラメータを長時間実行タスクに渡します。

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

onPauseのasynchTaskとprogressDialogをキャンセルします

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

JAL

私はいくつかのコードを持っています こちら

2
JAL

以下のコードをコピーして、非同期タスク内に貼り付けるだけです。

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

}

これに従ってください、キャンセルボタンのみが非同期で表示され、キャンセルボタンをクリックして呼び出しが終了します

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


    }
0
Ahmad Arslan