2011年3月28日月曜日

Android 切り替えたTabを戻るボタンで戻す

TabHostを使ったタブは戻るボタンで前のタブに戻るんじゃなくて、tab使ったアクティビティ起動前の状態に戻るので何か直感的でない。・・・ような気がする。少なくとも私の感覚的には前にいたタブに戻ってほしい。

何か良い方法はないか。
とりあえず困ったときはググってみる。


見つからない。良いクエリも思い浮かばないしな。
諦めた。調べるのは。

よし、自分で書いてみるか。

要は、戻るボタンを押されたイベントを奪ってしまえば良いんでしょ。で、前にいた状態にsetCurrentTabしてやればいけるはず。

まずはタブ遷移の履歴用のリストを用意して、タブが変わったイベントで履歴リストに追加する。
    protected ArrayList<String> history;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        history = new ArrayList<String>();
        TabHost tabHost = getTabHost();

        tabHost.setOnTabChangedListener(new OnTabChangeListener() {
            @Override
            public void onTabChanged(String arg0) {
                history.add(arg0);
            }
        });

        /* 省略 タブの追加(tabHost.addTab) */
    }
historyには最初の状態のタグを入れるのはTabChangedListenerではaddされないので自分でaddして入れておく。 ※追記 tabHost.addTabより前にtabHost.setOnTabChangedListenerをしていれば良いだけでした。ソースも一部修正(省略の位置変更、history.add削除)。

これでタブの遷移履歴は持つようになったので、これを見て戻るボタンの動きを変えれば良し。dispatchKeyEventをオーバーライド。
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (history.size() > 1 &&
            event.getAction() == KeyEvent.ACTION_DOWN &&
            event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            history.remove(history.size() - 1);
            String tag = history.get(history.size() - 1);
            history.remove(history.size() - 1);
            getTabHost().setCurrentTabByTag(tag);
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
historyが1つより多い(初期状態のデフォルトタブでない)、かつ、戻るボタンが押されたときだけ、処理を奪って変更する。それ以外のときは、親を呼んで返す。奪った処理では、historyの最後の状態を消す。setCurrentするときにまたonTabChangedでhistoryにaddされるので、1つ前のタブもremoveしておいてからsetCurrentする。でtrueを返す。日本語で説明するのは難しいなぁ。。上手く言語化できない。情報の伝達に齟齬が発生するかもしれない。なので読まないで。コード自体は簡単でまんまなのでコードだけ読んだ方が早い。


これで戻るボタンで前のタブに戻っているような動きにはなった。でも、これだとタブ内の他のActivityで戻るボタン使いたいときには上手くいかないこともあるのかな。試した感じでは問題なさそうだが。あと、これtabを遷移しまくると、戻るボタンでアプリケーション終えるのが大変とか。ちょっと難あり。自分で書いてみるとこんな程度か。