【お手軽】Backボタンを二回タップすると終了する例の機能を実装してみる
こんにちは2013年。こむろです。
今年ものんべんだらりんと技術ネタをあげていこうと思います。よろしくお願い致します。
Androidでは、たまにBackボタンを二回タップしないと終了しないアプリケーションがあります。Google推奨の標準のUIではないですが、結構メジャーなアプリケーションで実装されているような気がします。Backボタンを一度タップしただけでは終了したくない場合、終了確認ダイアログを出す方法もありますが、今回は、Backボタンを二回タップすると終了する機能をさくっと作ってみたいと思います。
この実装方法よりもスマートでエレガントな実装方法があれば、是非教えてください
Backボタンを検知する
何のボタンがタップされたかは、物理キー、ソフトウェアキーボードを含めて、Activity#dispatchKeyEvent で検知可能です
@Override public boolean dispatchKeyEvent(KeyEvent event) { return super.dispatchKeyEvent(event); }
KeyEvent event のkeyCodeを評価すればOKです。KeyEvent に定数が定義してありますので、それを利用します。
Backボタンを検知。KeyEvent#KEYCODE_BACK を使います
@Override public boolean dispatchKeyEvent(KeyEvent event) { // Backボタン検知する if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) { Log.d(TAG, "Press back button"); return false; } // Backボタンに関わらないボタンが押された場合は、通常処理. return super.dispatchKeyEvent(event); }
ちなみに上記のコード実装をすると、絶賛Backボタンの動作がすべて無視されるので、アプリが終了できなくなるのでご注意を。
Backボタンを二度タップされたことを検知する
特に思いつかなかったので、タップ回数の状態をboolean変数で持たせてみます。また規定時間内に二度タップされたことを検知する必要があるので、何かしらTimerが必要になります。ちょうどAndroidのパッケージに CountDownTimer というabstract classがあるので、これを利用してみます。
// onFinish(), onTick() keyEventTimer = new CountDownTimer(1000, 100) { @Override public void onTick(long millisUntilFinished) { Log.d(TAG, "call onTick method"); } @Override public void onFinish() { Log.d(TAG, "call onFinish method"); } };
abstract classのため、そのままインスタンス化はできないので、実装を書きます。引数の前方の数値は、Finishまでの時間をmsで指定します。後方の数値は、Finishまでの刻み時間の指定です。この場合は、1秒後にonFinish()が実行され、その間に10回のonTick()が実行され(るはずです)ます。
完全体
全体のコードはこんなかんじでしょうか
import android.os.Bundle; import android.os.CountDownTimer; import android.app.Activity; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.widget.Toast; public class MainActivity extends Activity { // Log用のTAG private static final String TAG = MainActivity.class.getSimpleName(); // BackボタンPress時の有効タイマー private CountDownTimer keyEventTimer; // 一度目のBackボタンが押されたかどうかを判定するフラグ private boolean pressed = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // onFinish(), onTick() keyEventTimer = new CountDownTimer(1000, 100) { @Override public void onTick(long millisUntilFinished) { Log.d(TAG, "call onTick method"); } @Override public void onFinish() { pressed = false; } }; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } @Override public boolean dispatchKeyEvent(KeyEvent event) { // Backボタン検知 if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) { if(!pressed) { // Timerを開始 keyEventTimer.cancel(); // いらない? keyEventTimer.start(); // 終了する場合, もう一度タップするようにメッセージを出力する Toast.makeText(this, "終了する場合は、もう一度バックボタンを押してください", Toast.LENGTH_SHORT).show(); pressed = true; return false; } // pressed=trueの時、通常のBackボタンで終了処理. return super.dispatchKeyEvent(event); } // Backボタンに関わらないボタンが押された場合は、通常処理. return super.dispatchKeyEvent(event); } }
実行結果
こんな感じです。1秒以内に再度Backボタンをタップするとアプリケーションを終了できます。1秒以上経過した場合は、またメッセージが出てきて終了されません。
Androidで標準で持っていない機能なので、標準のUIからは外れるんだろうなーとは思いますが、要件として必要になることがあるかもしれないので、試しに実装してみました。
Happy Android Life!