Android平台通过ActivityGroup实现类似IOS的UINavigationController

android程序中最基本的组成部分是activity,一个程序有多个activity,当启动一个新的activity的时候,新的activity会出现在屏幕上覆盖旧的activity;当这个activity finish()的时候,之前的activity重新显示出来.

简单的说,这是一个类似于栈的结构,即原有activity A1:[A1]

现在新开activity A2:[A1 A2]

当A2finish的时候,再显示A1:[A1]

这符合栈的特点,即后入先出,也符合一般人的思考逻辑,及返回键返回到之前的页面.

但是这样的结构有一个局限性,这样启动的activity都是我们通过Activity.startActivity(intent)这种方式启动的,是属于全屏的.

当我们只是想在一个页面的某个部分去启动一个activity,而且还保持这种层次结构,应该如何进行呢?

在ios平台上最基本的元素是ViewController和Controller对应的View,因此ios平台上提供了一个以UIVIEW为元素的栈来时限这样的功能,称为UINavigationController.这里不讨论它的使用,有兴趣的同学可以自己去学习.这里重点说明一下如何用ActivityGroup来实现类似的功能.


[java]  view plain copy
  1. package com.zz;  
  2.   
  3. import java.util.Stack;  
  4. import java.util.UUID;  
  5.   
  6. import android.app.ActivityGroup;  
  7. import android.content.Intent;  
  8. import android.os.Bundle;  
  9. import android.view.KeyEvent;  
  10. import android.view.View;  
  11. import android.widget.LinearLayout;  
  12.   
  13. /** 
  14.  * 各个Tab对应的Activity的父类 
  15.  *  
  16.  * @author zhouzhe@lenovo-cw.com 
  17.  */  
  18. public abstract class ActivityStack extends ActivityGroup {  
  19.   
  20.     /** 一个activity的栈用来存放缓存的View */  
  21.     Stack<StackElement> stack;  
  22.   
  23.     @Override  
  24.     protected void onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.         stack = new Stack<StackElement>();  
  27.     }  
  28.   
  29.     /** 
  30.      * 一个抽象方法,返回一个LinearLayout实际上是一个区域用来展示栈内的view 
  31.      *  
  32.      * @return 
  33.      * @author zhouzhe@lenovo-cw.com 
  34.      * @time 2012-2-20 
  35.      */  
  36.     abstract LinearLayout getMainView();  
  37.   
  38.     /** 
  39.      * 用来向栈顶添加一个元素并显示 
  40.      *  
  41.      * @param intent 
  42.      *            跟启动activity的intent一样 
  43.      * @author zhouzhe@lenovo-cw.com 
  44.      * @time 2012-2-20 
  45.      */  
  46.     void addView(Intent intent) {  
  47.         // 生成一个字符串,作为启动activity的key,后面在移除了view以后,要通过这个key来finish对应的activity  
  48.         String str = UUID.randomUUID().toString();  
  49.         getMainView().removeAllViews();  
  50.         View view = getLocalActivityManager().startActivity(str, intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)).getDecorView();  
  51.         // 注意layoutParams,否则会造成无法充满的问题  
  52.         getMainView().addView(view, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));  
  53.         getMainView().requestFocus();  
  54.         // 生成一个栈内缓存对象,主要包括activity对应的view和对应的key,并压入栈中  
  55.         StackElement component = new StackElement(str, view);  
  56.         stack.add(component);  
  57.     }  
  58.   
  59.     /** 
  60.      * 弹栈操作 
  61.      *  
  62.      * @return 
  63.      * @author zhouzhe@lenovo-cw.com 
  64.      * @time 2012-2-20 
  65.      */  
  66.     int pop() {  
  67.         // 先判断是否已经是栈顶元素了  
  68.         int size = stack.size();  
  69.         StackElement element = null;  
  70.         if (size > 1) {  
  71.             // 如果不是,获取到栈顶元素,并销毁.然后再获取当前的栈顶元素,显示到activityGroup  
  72.             element = stack.pop();  
  73.             getLocalActivityManager().destroyActivity(element.getTag(), true);  
  74.             element = stack.peek();  
  75.         } else if (size == 1) {  
  76.             // 如果是栈顶元素,直接显示  
  77.             element = stack.peek();  
  78.         }  
  79.         getMainView().removeAllViews();  
  80.         getMainView().addView(element.getView());  
  81.         getMainView().requestFocus();  
  82.         return stack.size();  
  83.     }  
  84.   
  85.     /** 
  86.      * 清空Stack,仅保留最底层的view 
  87.      */  
  88.     void clearStack() {  
  89.         int size = stack.size();  
  90.         if (size > 1) {  
  91.             for (int i = 0; i < size - 1; i++) {  
  92.                 stack.pop();  
  93.             }  
  94.         }  
  95.     }  
  96.   
  97.     void clearAll() {  
  98.         int size = stack.size();  
  99.         if (size > 0) {  
  100.             for (int i = 0; i < size; i++) {  
  101.                 StackElement element = stack.pop();  
  102.                 getLocalActivityManager().destroyActivity(element.getTag(), true);  
  103.             }  
  104.         }  
  105.     }  
  106.   
  107.     @Override  
  108.     protected void onDestroy() {  
  109.         super.onDestroy();  
  110.     }  
  111.   
  112.     @Override  
  113.     public boolean dispatchKeyEvent(KeyEvent event) {  
  114.         // 对键盘事件的处理,如果当前activityGroup中已经载入了activity,则分发给子activity处理,如果没有则自己处理.  
  115.         if (getCurrentActivity() != null) {  
  116.             return getCurrentActivity().dispatchKeyEvent(event);  
  117.         } else {  
  118.             return super.dispatchKeyEvent(event);  
  119.         }  
  120.   
  121.     }  
  122.   
  123. }  

这是一个比较简单的类,简单说明一下流程.

activityGroup载入activity,A1的时候,使用addView方法,压入栈中.在加载A2的时候,还是调用activityStack的addView方法,移除A1,加入A2并压入栈中.在finish A2的时候,不能直接finish,这样整个activityGroup都被finish掉了.要调用activityStack的pop方法,移除栈顶元素,销毁,显示移除后的栈顶元素.同时要注意分发键盘的back事件,同样是要用pop方法取代默认的finish方法,这样即可完成一个类似于uinavigationcontroller的栈.


有兴趣的同学看一下吧.

源代码 http://download.csdn.net/detail/zz880329/4076318

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值