Tab内の Activity 切り替えは、ActivityGroup で

Tab内の Activity を切り替える方法に、TabHost が、TabSpec を内部で java.util.List で管理しているのを
リフレクションを屈指して切り替えるなんて、方法は、ダメである。
OSのバージョンが上がって中のTabHost 内のコードが変わったらNGだし、一見、簡単そうだけど、
結構、TabWidget の部分が、深いリフレクションになってしまう。

やはり、Tab内でのActivity切り替わることを前提とした、ActivityGroup を使うしかないと思う。

ActivityGroup を使うところまでは、皆、すぐに書けると思うが、

問題は ActivityGroup で切り替わったタブから別のタブに切り替え、また元の ActivityGroup を使用したタブに
タブを切り替えで戻った時に、初期表示させることである。


Handler を使うと簡単に実現できる。

以下、サンプルで、まずは、ActivityGroup

import android.app.ActivityGroup;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.ViewGroup;
import android.view.Window;
/**
 * ParentActivityGroup
 */

public class ParentActivityGroup extends ActivityGroup{
   private ViewGroup container;
   public static Handler Phandler;  // static で宣言

   @Override
   protected void onCreate(Bundle savedInstanceState){
      super.onCreate(savedInstanceState);
      setContentView(R.layout.container);
      container = (ViewGroup)findViewById(R.id.container);

      // 任意の TabChild1Activity を 初期表示
      showChild1();

      Phandler = new Handler(){
         @Override
         public void handleMessage(Message msg){

            Log.d("sample","# handleMessage  what = "+msg.what+"  obj = "+msg.obj);
            Log.d("sample","# getCurrentActivity().getLocalClassName()  = "+getCurrentActivity().getLocalClassName());
            Log.d("sample","# getCurrentActivity().getClass().getName() = "+getCurrentActivity().getClass().getName());

            removeMessages(0);
            showChild1();
         }
      };

   }
   // TabChild1Activity を表示
   public void showChild1(){
      container.removeAllViews();
      Intent intent = new Intent(this, TabChild1Activity.class);
      intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
      Window window = getLocalActivityManager().startActivity("child1Activity",intent);
      container.addView(window.getDecorView());
   }
   // TabChild2Activity を表示
   public void showChild2(){
      container.removeAllViews();
      Intent intent = new Intent(this, TabChild2Activity.class);
      intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
      Window window = getLocalActivityManager().startActivity("child2Activity",intent);
      container.addView(window.getDecorView());
   }
}

ちょっと余計に書いたログは、ActiGroup が Activity の切り替え前に表示していた Activityのクラスを示すもの。

getCurrentActivity().getLocalClassName() は、AndroidManifest.xml で定義する package を省いたクラス名
getCurrentActivity().getClass().getName() で手慣れたクラス名を取得でき違和感がない。


タブ内の Actovity 側から、
  *1.showChild2();
のように呼び出して切り替えを実行する。

TabActivity の方では、OnTabChangeListener を定義

public class TabReplaceActivity extends TabActivity{
   protected static String INIT_TAG = "Tab1";

   private TabHost host;

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.tabmain);

      host = getTabHost();

      // 1番目のタブに、ActivityGroup を指定
      TabSpec tab1 = host.newTabSpec(INIT_TAG);
      tab1.setIndicator("Edit", getResources().getDrawable(android.R.drawable.ic_menu_edit));
      tab1.setContent(new Intent(this,ParentActivityGroup.class));
      host.addTab(tab1);

      TabSpec tab2 = host.newTabSpec("Tab2");
      tab2.setIndicator("Help", getResources().getDrawable(android.R.drawable.ic_menu_help));
      tab2.setContent(new Intent(this,HelpActivity.class));
      host.addTab(tab2);

      // 初期表示
      host.setCurrentTabByTag(INIT_TAG);

      // OnTabChangeListener で、通知
      host.setOnTabChangedListener(new TabHost.OnTabChangeListener(){
         @Override
         public void onTabChanged(String tabId){

            // ActivityGroup のタブに切り替わった時のみ、Handler でメッセージ送信
            if (tabId.equals(INIT_TAG)){
               ParentActivityGroup.Phandler.sendMessage(Message.obtain());
               // 情報を渡すなら以下、
               //Message message = TabParentActivityGroup.Phandler.obtainMessage(0,INIT_TAG);
               //TabParentActivityGroup.Phandler.sendMessage(message);

            }
         }
      });

   }
}

*1:ParentActivityGroup)getParent(