您的位置:首页 > 移动开发 > Android开发

程序猿媛 八:Android侧滑栏+底部导航栏(选项卡)

2014-09-15 13:16 393 查看

Android侧滑栏+底部导航栏(选项卡)

声明:博文为原创,文章内容为,效果展示,思路阐述,及代码片段。
转载请保留原文出处“http://my.oschina.net/gluoyer/blog”,谢谢!
引子:更新手机QQ5.1,发现小企鹅整合了侧滑栏,加底部导航栏的风格,跟风一下。
展示应用下载:程序猿媛2.0
实现效果:


 

 


本文介绍:
FragmentManager管理底部导航栏对应Fragment内容切换。
利用Slidingmenu展示侧滑栏;

FragmentManager管理底部导航栏对应Fragment内容切换:

    底部导航栏,以前介绍过“程序猿媛二:Android底部导航栏(选项卡)”,利用RadioGroup做导航栏,ViewPager结合Fragment管理显示页面。
    此处涉及到图文显示,以及需要扩展(实际应用中,显示新消息提醒等),使用自定义导航项布局,并在代码中管理点击切换内容的方式。同时,考虑到“程序猿媛二”中,定义及管理对应关系有点繁琐的问题,特意进行了代码优化,使得管理更加方便。

    初始化导航内容:

定义管理映射:
private SparseArray<BaseFragment> navigateMap = new SparseArray<BaseFragment>();

// 添加导航内容
setContentView(R.layout.slide_menu_content_frame);
navigateMap.clear();
mapNaviToFragment(R.id.navi_item_home, new HomeFragment()); // 首页
mapNaviToFragment(R.id.navi_item_work_notes, new WorkNotesFragment()); // 工作笔记
mapNaviToFragment(R.id.navi_item_third_libs, new ThirdLibsFragment()); // 第三方
// 设置首页默认显示
replaceFragment(fm, R.id.navi_item_home); // 执行内容切换方法,后续描述

/**
* 初始化map
* @param id 导航view ID
* @param fragment
*/
private void mapNaviToFragment(int id, BaseFragment fragment) {
View view = findViewById(id);
Utils.logh(TAG, "mapNaviToFragment " + id + " view: " + view);
view.setOnClickListener(this); // 设置导航点击事件
view.setSelected(false); // 默认添加时,非选中
navigateMap.put(id, fragment); // 添加到管理映射
}


    可以看到初始化map(被系统建议使用SparseArray替代HashMap,不了解的问度娘吧)时,直接用View的id作为key。如此,后续点击切换时,就可以直接通过View的选中状态来判断,当前点击后,是否需要替换显示内容。不再需要额外定义标签,及记录当前选择标签等;代码复用也更方便。

点击切换处理

/**
* 点击后,切换内容
* @param view 点击view
* @return 点击view,是否为导航view
*/
private boolean clickSwitchContent(View view) {
int id = view.getId();
if(navigateMap.indexOfKey(id) < 0) {
// 点击非导航view
return false;
}
Utils.logh(TAG, "switchContent " + id + " select: " + view.isSelected() + " view: " + view);
if(!view.isSelected()) {
// 当前非选中状态:需切换到新内容
replaceFragment(getSupportFragmentManager(), id);
} else {
Utils.logh(TAG, " ignore --- selected !!! ");
}
return true;

}

@Override
public void onClick(View v) {
if(clickSwitchContent(v)) {
return ;
}
// 处理其他点击事件
}


    实现系统onClick点击方法时,封装了clickSwitchContent方法,通过navigateMap查看点击View是否为导航View。非导航View,返回处理其他点击事件;是导航View,根据view的选中状态,非选中时,切换到新的Fragment显示内容。

执行内容切换

/**
* 执行内容切换
* @param fm
* @param id 导航view ID
*/
private void replaceFragment(FragmentManager fm, int id) {
Utils.logh(TAG, "replaceFragment EntryCount: " + fm.getBackStackEntryCount()
+ " size: " + (null == fm.getFragments() ? "0[null]" : fm.getFragments().size()));
String tag = String.valueOf(id);
// 执行替换
FragmentTransaction trans = fm.beginTransaction();
if(null == fm.findFragmentByTag(tag)) {
trans.replace(R.id.content_frame, navigateMap.get(id), tag);
// 不存在时,添加到stack,避免切换时,先前的被清除{fm.getFragments()}
// {存在时,不添加,避免BackStackEntry不断累加}
Utils.logh(TAG, "null +++ add to back");
trans.addToBackStack(tag);
} else {
trans.replace(R.id.content_frame, fm.findFragmentByTag(tag), tag);
}
trans.commit();
Utils.logh(TAG, "replace map: " + navigateMap.get(id) + "\n" +
"---- fm tag: " + fm.findFragmentByTag(tag));
// 重置导航选中状态
for(int i=0, size=navigateMap.size(); i<size; i++) {
int curId = navigateMap.keyAt(i);
Utils.logh(TAG, "curId: " + curId);
if(curId == id) {
findViewById(id).setSelected(true);
} else {
findViewById(curId).setSelected(false);
}
}
}


    方法中,主要两部分功能:执行替换;重置导航选中状态。

    这里主要介绍下,执行替换中,addToBackStack的处理。关于FragmentManager的介绍,比比皆是,却翻来覆去。度娘说,大家都转疯了。

    addToBackStack,大家应该都知道,是一个历史操作的记录。但此处应用,是非常规的,作为了一个绑定标识。抛开系统源码的讲解,和官方文档的不尽翻译。用更直观的方式,阐述下此处对addToBackStack的使用。

    如果,不用addToBackStack方法,打印如下左侧,用addToBackStack方法,打印如下右侧:





很明显,不加到backstack的话,切换过程中,系统会销毁之前的Fragment,再回来的时候,要重新绑定,创建,通过getFragments().size()方法获取的FragmentManager中的Fragment列表也是不同的:只存放当前;存放所有添加到backstack的{size比我们初步想到的貌似多了1,要记得侧滑栏也是一个Fragment哈}。

    当然,addToBackStack也可以不做限制,每次都添加,只是通过getBackStackEntryCount()方法会看到,记录会不断累积,而我们又不需要(当然,你要非需要,额外处理一下),所有就只是判断一下,不做重复添加了,毕竟,使用很另类,只是绑定标识,而已。

    哈,简化过的几个方法,处理了原本对应繁琐的问题,也有更好的复用性。

 

利用Slidingmenu展示侧滑栏:

    侧滑栏的应用介绍可以参照,程序猿媛 七:slidingmenu侧滑栏导航。原来整理成了jar包放到了libs里面。考虑出现问题时,更容易跟踪等情况,将源码放到工程extras目录下(碰到导入相关问题的话,请先度娘一哈)。完整源码请膜拜Jeremy Feinstein的“SlidingMenu-GitHub”。

   slidingmenu目录下,只放置了供大家引用的基础工程,同时,把动画相关,从源码示例工程,提取出CustomAnimation.java文件,调用时,如下即可:

SlidingMenu sm = getSlidingMenu();

sm.setBehindCanvasTransformer((new CustomAnimation()).getCustomZoomAnimation());

当然,你也可以加入自己实现的动画显示方式。   欢迎反馈,后续丰富动画代码。

 

全文完,希望对您有帮助,谢谢!

展示应用下载:程序猿媛2.0

转载请保留原文出处“http://my.oschina.net/gluoyer/blog”,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: