AndroidTVを触る機会があったので、備忘録としてKey制御周りについて記載しようと思います。
#フォーカスがViewを重ねたことによって迷子になった場合
下記の図のように、何かのトリガーによって全体にViewを重ねた際に、フォーカスが下のボタンに当たったままになってしまい、重ねたViewのボタンの制御ができなくなってしまいます。
そういった場合は、全体にViewを重ねるタイミングで重ねたViewのボタンへのフォーカスを当てる処理を追加してあげることで解決することができます。
Button belowViewButton = (Button)view.findViewById(R.id.belowViewButton);
belowViewButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
// トップのViewを表示
topView.show();
// トップのViewに表示しているボタンへフォーカスを当てる
topViewButton.setFocusable(true);
topViewButton.requestFocus();
}
});
#Fragment内でKeyEventを取得する場合
Fragment内でKeyEventを取得する場合はフォーカスが当たっているオブジェクトに対してOnKeyListenerを定義して上げる必要があるのですが、AndroidTVの場合キーの操作によってフォーカスが移り変わっていってしまうため、OnKeyListenerが定義されていないオブジェクトにフォーカスが当たっている場合はKeyEventが取得できなくなってしまいます。
Activity内ならフォーカス関係なくKeyEventを取得することできるためActivity→Fragmentの流れでKeyEventを通知して上げることで解決できます。
#どうしてもFragment内だけでKeyEventの処理を済ませたい場合
下記のように、フォーカスが当たる予定の全てのオブジェクトに対してOnKeyListenerを定義することになります。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_main, container, false);
Button button1 = (Button)view.findViewById(R.id.button1);
// button1へKeyEventを設定
setKeyEvent(button1);
Button button2 = (Button)view.findViewById(R.id.button2);
// button2へKeyEventを設定
setKeyEvent(button2);
return view;
}
private void setKeyEvent(Button button) {
button.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// ACTION_DOWNとACTION_UPの両方が取れるのでACTION_DOWNのみ受け付けるように
if (event.getAction() != KeyEvent.ACTION_DOWN) return false;
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
// バックキーが押されたときの処理
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
// D-padのCenterボタンが押されたときの処理
return true;
case KeyEvent.KEYCODE_DPAD_UP:
// D-padのUpボタンが押されたときの処理
return true;
case KeyEvent.KEYCODE_DPAD_DOWN:
// D-padのDownボタンが押されたときの処理
return true;
case KeyEvent.KEYCODE_DPAD_LEFT:
// D-padのLeftボタンが押されたときの処理
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
// D-padのRightボタンが押されたときの処理
return true;
}
return false;
}
});
}