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来实现类似的功能.
- packagecom.zz;
- importjava.util.Stack;
- importjava.util.UUID;
- importandroid.app.ActivityGroup;
- importandroid.content.Intent;
- importandroid.os.Bundle;
- importandroid.view.KeyEvent;
- importandroid.view.View;
- importandroid.widget.LinearLayout;
- /**
- *各个Tab对应的Activity的父类
- *
- *@authorzhouzhe@lenovo-cw.com
- */
- publicabstractclassActivityStackextendsActivityGroup{
- /**一个activity的栈用来存放缓存的View*/
- Stack<StackElement>stack;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- stack=newStack<StackElement>();
- }
- /**
- *一个抽象方法,返回一个LinearLayout实际上是一个区域用来展示栈内的view
- *
- *@return
- *@authorzhouzhe@lenovo-cw.com
- *@time2012-2-20
- */
- abstractLinearLayoutgetMainView();
- /**
- *用来向栈顶添加一个元素并显示
- *
- *@paramintent
- *跟启动activity的intent一样
- *@authorzhouzhe@lenovo-cw.com
- *@time2012-2-20
- */
- voidaddView(Intentintent){
- //生成一个字符串,作为启动activity的key,后面在移除了view以后,要通过这个key来finish对应的activity
- Stringstr=UUID.randomUUID().toString();
- getMainView().removeAllViews();
- Viewview=getLocalActivityManager().startActivity(str,intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)).getDecorView();
- //注意layoutParams,否则会造成无法充满的问题
- getMainView().addView(view,newLinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT));
- getMainView().requestFocus();
- //生成一个栈内缓存对象,主要包括activity对应的view和对应的key,并压入栈中
- StackElementcomponent=newStackElement(str,view);
- stack.add(component);
- }
- /**
- *弹栈操作
- *
- *@return
- *@authorzhouzhe@lenovo-cw.com
- *@time2012-2-20
- */
- intpop(){
- //先判断是否已经是栈顶元素了
- intsize=stack.size();
- StackElementelement=null;
- if(size>1){
- //如果不是,获取到栈顶元素,并销毁.然后再获取当前的栈顶元素,显示到activityGroup
- element=stack.pop();
- getLocalActivityManager().destroyActivity(element.getTag(),true);
- element=stack.peek();
- }elseif(size==1){
- //如果是栈顶元素,直接显示
- element=stack.peek();
- }
- getMainView().removeAllViews();
- getMainView().addView(element.getView());
- getMainView().requestFocus();
- returnstack.size();
- }
- /**
- *清空Stack,仅保留最底层的view
- */
- voidclearStack(){
- intsize=stack.size();
- if(size>1){
- for(inti=0;i<size-1;i++){
- stack.pop();
- }
- }
- }
- voidclearAll(){
- intsize=stack.size();
- if(size>0){
- for(inti=0;i<size;i++){
- StackElementelement=stack.pop();
- getLocalActivityManager().destroyActivity(element.getTag(),true);
- }
- }
- }
- @Override
- protectedvoidonDestroy(){
- super.onDestroy();
- }
- @Override
- publicbooleandispatchKeyEvent(KeyEventevent){
- //对键盘事件的处理,如果当前activityGroup中已经载入了activity,则分发给子activity处理,如果没有则自己处理.
- if(getCurrentActivity()!=null){
- returngetCurrentActivity().dispatchKeyEvent(event);
- }else{
- returnsuper.dispatchKeyEvent(event);
- }
- }
- }
这是一个比较简单的类,简单说明一下流程.
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