【Android】Fragment単位でキーイベントを管理する

Androidのキーイベントの管理はActivity#onKeyDownで行うことが出来ます。

が、Fragmentにはそれに該当するメソッドがありません。呼び出したActivityのonKeyDownを実行してしまいます。

まぁ色んなActivityで再利用されることを前提にしているので、「Activityとの結合度を下げる」と言う観点から言えば筋が通っているんですが、Fragmentレベルでキーイベントを取得したいことも結構あります。DialogFragmentとかだと特に。

そんなわけで今回はFragmentそのものにキーイベントのListenerを登録します。

View.OnKeyListenerを設定する

キーイベントをフックする方法としてActivity#onKeyDownを使う他に、View#setOnKeyListenerView.OnKeyListenerを登録する方法があります。

FragmentはonCreateViewで返ってきたViewを表示します。このViewに対してOnKeyListenerを設定すれば上手く行きそうです。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    final View v = inflater.inflate(R.layout.fragment, container, false);

    v.setOnKeyListener(new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            // KeyEvent.ACTION_DOWN以外のイベントを無視する
            // (これがないとKeyEvent.ACTION_UPもフックしてしまう)
            if(event.getAction() != KeyEvent.ACTION_DOWN) {
                return false;
            }

            switch(keyCode) {
                case KeyEvent.KEYCODE_VOLUME_UP:
                    // TODO:音量増加キーが押された時のイベント
                    return true;
                case KeyEvent.KEYCODE_VOLUME_DOWN:
                    // TODO:音量減少キーが押された時のイベント
                    return true;
                default:
                    return false;
            }
        }
    });
    
    // View#setFocusableInTouchModeでtrueをセットしておくこと
    v.setFocusableInTouchMode(true);

    return v;
}

まとめ

これだけです。簡単ですね。

とにかくFragmentが持っているViewに対してOnKeyListenerが設定出来ればいいので、Activity側からFragment#getViewを呼び出し、同じ要領でListenerを設定すれば生成したFragment一つ一つに別のイベントを設定することも出来ます。

参考