Android开发 ActivityGroupd应用底部导航栏
2015-11-19 21:44
459 查看
在android应用中底部导航栏可以说是十分常见的,如新浪微博,微信等都是这种设计,大家在做这种应用第一反应就是使用TabActivity,今天就来分享下如何用ActivityGroup来代替TabActivity,以及这样使用的优点。
ActivityGroup是Google提供的一个非常优秀的API,而TabActivity是ActivityGroup唯一的一个子类。
首先来说ActivityGroup的优秀之处以及它的必要性,它为开发者提供了一种可能,这种可能不将Activity作为屏幕的顶级元素(Context)呈现,而是嵌入到ActivityGroup当中。这是一种极大的飞跃,它将场景(Context)细分化了,ActivityGroup是一个主场景,而用户可以通过导航按钮来切换想要的子场景。如使用微博功能,它是一个相当宏大的场景,具有看最新的广播信息、自己发微博、修改资料等子场景,用户可以通过按钮来切换到想要的子场景,而这个子场景仍活动于主场景之中。让一个主场景能拥有多个逻辑处理模块,主场景不再负责子场景逻辑,主场景只负责切换场景的逻辑,即每一个Activity(子场景)拥有一个逻辑处理模块,一个ActivityGroup有多个Activity,却不干预Activity的逻辑,这无疑细分化和模块化了逻辑代码。ActivityGroup和它将要内嵌的Activity所要实现的功能完全可以只用一个Activity来完成,你可以试想,当你把一个ActivityGroup和它所拥有的Activity的逻辑代码放在一个Activity中时,那这个Activity会拥有多少行代码,为维护带来非常的不便。
再来说说TabActivity的不足之处,首先,TabActivity自己独有的视图几乎没人使用(也就是难看的标签页按钮形式),大多数开发者用到的特性几乎都是从ActivityGroup继承下来的。还有就是TabActivity的强制依赖关系,它的布局文件必须将TabHost作根标签,并且id必须为”@android:id/tabhost”,必须有TabWidget标签,且它的id必须是”@android:id/tabs”,还有加载Activity的View容器,id必须为@android:id/tabcontent。光是强制依赖关系,我就觉得不是很舒服。而且在android3.0以后已经建议用Fragment来代替TabActivity了。只是由于目前为了要兼容3.0之前的版本,Fragment还没有被开发者们所普及。
下面就来看下这次食物库重构后的用ActivityGroup来实现的主页面架构吧:
可以看到在“主场景”MainActivityGroup中基本没有任何逻辑代码,只有各个“子场景”切换的逻辑,而子场景的切换用了一个ActivityGroupManager类来管理,这样又起到了代码分离的作用,
值得一说的是在ActivityGroupManager类中的showContainer ()方法并没有像网上的做法这样:
这种做法看似代码逻辑更简单,但是这样就会导致每次切换“子场景”的时候都会把已经加载过的View remove掉,一方面性能有所欠缺,另一个方面“子场景”的状态无法记住。而现在的做法就很好的解决了上面的问题。
好了,然后就是各个“子场景”(Activity)的代码了,每个“子场景”的逻辑各自独立,这里就不上代码了。
这里还有一个需要提到的是底部导航栏的实现,由于android没有像iOS那样预定好的组件,只有自己定义一个布局了,这里我用到的是用RadioGroup来实现类似微信的底部导航栏效果,下面是布局代码,在其他使用到的地方直接include进来就可以了。
ActivityGroup是Google提供的一个非常优秀的API,而TabActivity是ActivityGroup唯一的一个子类。
ActivityGroup的优点
首先来说ActivityGroup的优秀之处以及它的必要性,它为开发者提供了一种可能,这种可能不将Activity作为屏幕的顶级元素(Context)呈现,而是嵌入到ActivityGroup当中。这是一种极大的飞跃,它将场景(Context)细分化了,ActivityGroup是一个主场景,而用户可以通过导航按钮来切换想要的子场景。如使用微博功能,它是一个相当宏大的场景,具有看最新的广播信息、自己发微博、修改资料等子场景,用户可以通过按钮来切换到想要的子场景,而这个子场景仍活动于主场景之中。让一个主场景能拥有多个逻辑处理模块,主场景不再负责子场景逻辑,主场景只负责切换场景的逻辑,即每一个Activity(子场景)拥有一个逻辑处理模块,一个ActivityGroup有多个Activity,却不干预Activity的逻辑,这无疑细分化和模块化了逻辑代码。ActivityGroup和它将要内嵌的Activity所要实现的功能完全可以只用一个Activity来完成,你可以试想,当你把一个ActivityGroup和它所拥有的Activity的逻辑代码放在一个Activity中时,那这个Activity会拥有多少行代码,为维护带来非常的不便。
TabActivity的不足
再来说说TabActivity的不足之处,首先,TabActivity自己独有的视图几乎没人使用(也就是难看的标签页按钮形式),大多数开发者用到的特性几乎都是从ActivityGroup继承下来的。还有就是TabActivity的强制依赖关系,它的布局文件必须将TabHost作根标签,并且id必须为”@android:id/tabhost”,必须有TabWidget标签,且它的id必须是”@android:id/tabs”,还有加载Activity的View容器,id必须为@android:id/tabcontent。光是强制依赖关系,我就觉得不是很舒服。而且在android3.0以后已经建议用Fragment来代替TabActivity了。只是由于目前为了要兼容3.0之前的版本,Fragment还没有被开发者们所普及。下面就来看下这次食物库重构后的用ActivityGroup来实现的主页面架构吧:
MainActivityGroup.java public class MainActivityGroup extends ActivityGroup implements OnCheckedChangeListener { private static final String RECORD = "record"; private static final String CATEGORY = "category"; private static final String MORE = "more"; private ActivityGroupManager manager = null; private FrameLayout container = null; private RadioGroup radioGroup; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_main); initView(); } private void initView() { radioGroup = (RadioGroup) findViewById(R.id.main_radio); radioGroup.setOnCheckedChangeListener(this); manager = new ActivityGroupManager(); container = (FrameLayout) findViewById(R.id.container); manager.setContainer(container); switchActivity(ActivityGroupManager.RECORD_ACTIVITY_VIEW, RECORD, RecordActivity.class); } @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.record_button: switchActivity(ActivityGroupManager.RECORD_ACTIVITY_VIEW, RECORD, RecordActivity.class); break; case R.id.category_button: switchActivity(ActivityGroupManager.CATEGORY_ACTIVITY_VIEW, CATEGORY, CategoryActivity.class); break; case R.id.more_button: switchActivity(ActivityGroupManager.MORE_AVTIVITY_VIEW, MORE, MoreActivity.class); break; default: break; } } private View getActivityView(String activityName, Class<?> activityClass) { return getLocalActivityManager().startActivity(activityName, new Intent(MainActivityGroup.this, activityClass)) .getDecorView(); } private void switchActivity(int num, String activityName, Class<?> activityClass) { manager.showContainer(num, getActivityView(activityName, activityClass)); } }
可以看到在“主场景”MainActivityGroup中基本没有任何逻辑代码,只有各个“子场景”切换的逻辑,而子场景的切换用了一个ActivityGroupManager类来管理,这样又起到了代码分离的作用,
ActivityGroupManager.java public class ActivityGroupManager { private static final String TAG = "frag_manager"; public static final int RECORD_ACTIVITY_VIEW = 0; public static final int CATEGORY_ACTIVITY_VIEW = 1; public static final int MORE_AVTIVITY_VIEW = 2; private HashMap<Integer, View> hashMap; private ViewGroup container; public ActivityGroupManager() { hashMap = new HashMap<Integer, View>(); } public void setContainer(ViewGroup container) { this.container = container; } public void showContainer(int num, View view) { if (!hashMap.containsKey(num)) { hashMap.put(num, view); container.addView(view); } for (Iterator<Integer> iter = hashMap.keySet().iterator(); iter.hasNext();) { Object key = iter.next(); View v = hashMap.get(key); v.setVisibility(View.INVISIBLE); } view.setVisibility(View.VISIBLE); } }
值得一说的是在ActivityGroupManager类中的showContainer ()方法并没有像网上的做法这样:
container.removeAllViews(); container.addView(view);
这种做法看似代码逻辑更简单,但是这样就会导致每次切换“子场景”的时候都会把已经加载过的View remove掉,一方面性能有所欠缺,另一个方面“子场景”的状态无法记住。而现在的做法就很好的解决了上面的问题。
好了,然后就是各个“子场景”(Activity)的代码了,每个“子场景”的逻辑各自独立,这里就不上代码了。
这里还有一个需要提到的是底部导航栏的实现,由于android没有像iOS那样预定好的组件,只有自己定义一个布局了,这里我用到的是用RadioGroup来实现类似微信的底部导航栏效果,下面是布局代码,在其他使用到的地方直接include进来就可以了。
<?xml version="1.0" encoding="utf-8"?> <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_radio" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="bottom|center" android:layout_marginBottom="-20dp" android:gravity="center" android:orientation="horizontal" android:padding="0dp" > <RadioButton android:id="@+id/record_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_weight="1.0" android:background="@null" android:button="@null" android:checked="true" android:drawableTop="@drawable/main_tab_record_selector" android:gravity="center" android:tag="record" /> <RadioButton android:id="@+id/category_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1.0" android:background="@null" android:button="@null" android:drawableTop="@drawable/main_tab_category_selector" android:gravity="center_horizontal" android:tag="category" /> <RadioButton android:id="@+id/more_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1.0" android:background="@null" android:button="@null" android:drawableTop="@drawable/main_tab_more_selector" android:gravity="center_horizontal" android:tag="more" /> </RadioGroup>
相关文章推荐
- Android 多线程及多线程中更新控件。
- android106 C基本数据类型
- Android的线程与线程池
- Android多线程编程
- Android View 事件分发处理流程
- Android项目重构之路:实现篇
- Android整合SlidingMenu和Actionbarsherlock解决Actionbar的冲突
- Android项目重构之路:界面篇
- android四大组件之Service 简单音乐播放器
- android中可能造成内存泄露的几种方式
- Android 省市县 三级联动(android-wheel的使用)
- Android回调机制
- Android 数据存储——Saving Files
- Android SlidingMenu 使用详解
- Android相对布局RelativeLayout
- Android开发之旅一初识Activity
- android学习ViewFlipper的使用
- Android进阶-多个ViewPager嵌套时事件传递的处理
- Android Resource Types之Drawable简介
- baseadapter适配器