这个问题应该涉及到所有实现了Tab风格的应用的设计

android的SDK提供了TabHost,TabWidget控件和TabActivity来支持这种方式,但是我感觉限制比较大,就尝试使用ActivityGroup去做。

在布局中,总要设置一个导航的菜单栏,iphone的是放在下面的。

总体上的布局都是如此的,整体的布局一般是一个RelativeLayout,下面放一个width是fill_parent的菜单栏。

contain是一个容器,我自己用过很多,比如LinearLayout,ViewAnimator等等,后者支持动画,不过其实这样的布局,上面的内容有点动画,看起来会有点怪。

ActivityGroup里面有个非常重要的成员,它是负责subActivity管理的——LocalActivityManager,可以通过getLocalActivityManager()来获的。

来看一下这个成员有什么作用,当然从老农的博客里面可以去寻找这个类的中文API啦~

public Activity getCurrentActivity()

返回当前的activity,也就是状态是running的subActivity,也就是getAcitivity(getCurrentId())的实现

public String getCurrentId()

见上条

public void removeAllActivities()

销毁所有的subActivity

public Activity getActivity(String id)

通过acitivityId找到这个group对应的Activity对象。

public Window destroyActivity(String id, boolean finish)

这个是负责结束某一个subActivity的,在每次我们开启一个新的activity的时候,往往给他一个activityId,然后我们就可以通过这个id去销毁他。

public Window startActivity(String id, Intent intent)

在当前的group里面运行一个新的subActivity,必须传入一个id去映射之,做为索引。这边的Intent和Activity里的Intent一样,我们也可以通过这个来传递参数。

这边有一个需要注意的就是subActivity的启动方式方面的问题:

SingleTop和平时不同,举个例子:a启动b,b启动a,这时候在acitivity的栈里面有个就有了两个a,而在acitivityGroup管理下的SingleTop启动,则是a->b,再b->a,则不会有两个a,则是跳入a的时候call他的newIntent()方法

所以在这边如果你要复用这个界面,我个人觉得可以用singleTop,不仅可以保存它的状态,也可以把后续的操作放在onNewIntent(Intent) 里面,和onCreate区分开来。

给出一段示例代码:

ActivityGroupTest
 1 public class AcitivityGroupTestActivity extends ActivityGroup {
2 LocalActivityManager activityManager;
3 Button b1, b2;
4 LinearLayout contain;
5 /** Called when the activity is first created. */
6 @Override
7 public void onCreate(Bundle savedInstanceState) {
8 super.onCreate(savedInstanceState);
9 setContentView(R.layout.main);
10
11 activityManager = getLocalActivityManager();
12
13 b1 = (Button) findViewById(R.id.button1);
14 b2 = (Button) findViewById(R.id.button2);
15
16 contain = (LinearLayout) findViewById(R.id.contain);
17
18 b1.setOnClickListener(new OnClickListener() {
19
20 @Override
21 public void onClick(View v) {
22 contain.removeAllViews();
23 Intent in = new Intent(AcitivityGroupTestActivity.this, Activity01.class);
24 in.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
25 //in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
26
27 Window mWindow = activityManager.startActivity("1", in);
28 contain.addView(mWindow.getDecorView());
29 Activity a1 = activityManager.getActivity("1");
30 Activity a2 = activityManager.getActivity("2");
31 System.out.println("a1:" + a1 + ",a2:" + a2);
32 }
33 });
34
35 b2.setOnClickListener(new OnClickListener() {
36
37 @Override
38 public void onClick(View v) {
39 contain.removeAllViews();
40 Intent in = new Intent(AcitivityGroupTestActivity.this, Activity02.class);
41 in.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
42 //in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
43 Window mWindow = activityManager.startActivity("2", in);
44 contain.addView(mWindow.getDecorView());
45 Activity a1 = activityManager.getActivity("1");
46 Activity a2 = activityManager.getActivity("2");
47 System.out.println("a1:" + a1 + ",a2:" + a2);
48 }
49 });
50 }
51 }

如果我们要给他们加上跳转,怎么做呢?

一种做法是做在subActivity里面的:

在subActiivity里面获取 getParent() 则就是我们的ActivityGroup,然后通过这个来跳转。

比如在subActivity01里面按button01,跳转到subActivity02,我们可以这么写。

subActivity直接跳转
 1 // for parent
2 AcitivityGroupTestActivity parent = (AcitivityGroupTestActivity) getParent();
3 final LinearLayout contain = (LinearLayout) parent.findViewById(R.id.contain);
4 contain.removeAllViews();
5 Intent in = new Intent(getParent(), Activity02.class);
6 in.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
7 LocalActivityManager manager = parent.getLocalActivityManager();
8 String currentId = manager.getCurrentId();
9 Window window = manager.startActivity("2", in);
10 contain.addView(window.getDecorView());
11 // 如果有必要可以杀死之前的activity
12 manager.destroyActivity(currentId, true);

但是要做的通用点,则需要想办法了。

我个人的做法是在ActivityGroup里面注册一个receiver去监听跳转的信息,并且获取参数,我的参数全部封装在一个bundle里,这个是一个统一的格式,当然也可以用自己喜欢的方式。

receiver
 1 final static public String LOAD_SUBACTIVITY = "load_subActivity";
2 final static public String SUBACTIVITY_NAME = "subActivity_name";
3 final static public String SUBACTIVITY_01 = "subActivity_01";
4 final static public String SUBACTIVITY_02 = "subActivity_02";
5 final static public String SUBACTIVITY_PARAM = "subActivity_param";
6
7 private BroadcastReceiver receiver = new BroadcastReceiver() {
8
9 @Override
10 public void onReceive(Context context, Intent intent) {
11 // 去接收
12 String action = intent.getAction();
13 if(action.equals(LOAD_SUBACTIVITY)) {
14 String subActivityName = intent.getStringExtra(SUBACTIVITY_NAME);
15 Bundle param = intent.getBundleExtra(SUBACTIVITY_PARAM);
16 loadSubActivity(subActivityName, param);
17 }
18 }
19 };
20
21 private void loadSubActivity(String id, Bundle param) {
22 contain.removeAllViews();
23 Class subActivityClass = getSubActivityClass(id);
24 if(subActivityClass != null) {
25 Intent in = new Intent(AcitivityGroupTestActivity.this, subActivityClass);
26 in.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
27 if(param != null) {
28 in.putExtra("param", param);
29 }
30 Window mWindow = activityManager.startActivity(id, in);
31 contain.addView(mWindow.getDecorView());
32 } else {
33 return;
34 }
35 }
36
37 private Class getSubActivityClass(String id) {
38 if(id.equals(SUBACTIVITY_01)) {
39 return Activity01.class;
40 } else if(id.equals(SUBACTIVITY_02)) {
41 return Activity02.class;
42 } else {
43 return null;
44 }
45 }

当然你要注意在ActivityGroup里面去的onCreate去注册监听,和在onDestroy注销之。

register
1 public void onCreate(Bundle savedInstanceState) {
2 ......
3 registerReceiver(receiver, new IntentFilter(LOAD_SUBACTIVITY));
4 }
5
6 protected void onDestroy() {
7 unregisterReceiver(receiver);
8 super.onDestroy();
9 }

 

如果大家有别的思路或者更好的做法可以交流。

mailto:yanyin1986@gmail.com