複数のActivityを管理するActivityGroup

Activityは基本的に1画面に1つですが、
ActivityGroupを使うことでまとめて扱うことができます。




まずはメイン画面となるActivityGroupを作成します。
ActivityではなくActivityGroupを継承してクラスを作成します。

public class TestActivityGroup extends ActivityGroup {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

ここにLocalActivityManagerという
Activityを管理するオブジェクトを追加します。
インスタンスを取得するためのgetLocalActivityManager()というメソッドは
ActivityGroupに用意されているメソッドです。
public class TestActivityGroup extends ActivityGroup {
  // アクティビティを管理するクラス
    private LocalActivityManager lam;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
	// インスタンスの取得
	lam = getLocalActivityManager();
    }
}

それではこのLocalActivityManagerを使って別のActivityを呼び出してやりたいと思います。
ここで行わないといけないのが
・利用するActivity情報を持ったIntentの生成
・LocalActivityManagerを使いIntentからWindowオブジェクトを生成
・配置するレイアウトを呼び出し、ViewGroupに追加
その際にWindowオブジェクトのメソッドgetDecorView()でViewを生成

記述としてはこのようになります。
public class TestActivityGroup extends ActivityGroup {
  // アクティビティを管理するクラス
    private LocalActivityManager lam;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
	// インスタンスの取得
	lam = getLocalActivityManager();

	// 利用したいActivityのインテントを生成
	Intent intent = new Intent(getApplicationContext(),
		jp.co.global.test.activitygroup.SubActivity1.class);
	// lamを使いインテントからWindowを生成
	Window window = lam.startActivity("10000", intent);
	ViewGroup group = (ViewGroup)findViewById(R.id.layout);
	// WindowのオブジェクトからView情報を取得しレイアウトにセットする
	group.addView(window.getDecorView());
    }
startActivityに与える第一引数の値はとりあえず10000としておきます。


これらの操作によってActivityGroupの中にActivityを配置することができました。
一つ一つはViewとして扱っていますが、内部の動作はActivityに記述した内容で動作します。

ActivityGroup自身も一つのActivityのためレイアウトを持っていますので、
グループ用のViewと個別のActivityを同時に持つことができます。


TestActivityGroup.java
public class TestActivityGroup extends ActivityGroup {
    private LocalActivityManager lam;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
	lam = getLocalActivityManager();
	setView(jp.co.global.test.activitygroup.SubActivity1.class);
	setView(jp.co.global.test.activitygroup.SubActivity2.class);
    }
    private void setView(Class<?> cls){
	Intent intent = new Intent(getApplicationContext(),cls);
	Window window = lam.startActivity("10000", intent);
	ViewGroup group = (ViewGroup)findViewById(R.id.layout);
	group.addView(window.getDecorView());
    }
main.xml
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:gravity="center_horizontal"
    	android:text="複数のActivityを扱うActivityGroup"
    	android:textSize="20sp"
    	android:textColor="#FFF"
    ></TextView>
</LinearLayout>
sub1.xml
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#FFF"
    >
    <TextView
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:gravity="center_horizontal"
    	android:text="1つ目のActivity"
    	android:textSize="20sp"
    	android:textColor="#F00"
    ></TextView>
</LinearLayout>
sub2.xml
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#0F0"
    >
    <TextView
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:gravity="center_horizontal"
    	android:text="2つ目のActivity"
    	android:textSize="20sp"
    	android:textColor="#00F"
    ></TextView>
</LinearLayout>

今回は説明用に内部の記述のほとんどないActivityを利用しましたが、
いくつか注意したいところがあります。
・画面の回転
画面の回転が発生するとActivityGroupと子のActivityはonDestroy()メソッドが発生します。
ここまではいいのですが、この後復帰する際に、ActivityGroup内のActivityで生成したViewは
新規で作り直されます。
つまり、子のActivityではBundleのsavedInstanceStateでデータの復帰を行えなくなってしまいます
内部の情報が回転によって欠落してしまわないように注意をする必要があります。
・ハードキーの感知
Activityを画面内に複数配置できるため、
画面内にハードキーの感知を行う処理が複数存在することになります。
このときハードキーの処理を感知するのはフォーカスを持っているActivityになります。
(ActivityGroup含む)
そのためハードキーの処理を記述したのに感知しないなどといった場合、
別のActivityがハードキーの処理を行ってしまっている可能性が高いので
感知先や、たとえばonKeyDownメソッドであればreturnの値を
適切に処理してやる必要があります。

ちなみにgetCurrentActivity()で子のActivityを取得するといった方法もあります。


以上です。

Leave a Reply