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

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

声明:博文为原创,文章内容为,效果展示,思路阐述,及代码片段。

转载请保留原文出处“http://my.oschina.net/gluoyer/blog”,谢谢!

引子:更新手机QQ5.1,发现小企鹅整合了侧滑栏,加底部导航栏的风格,跟风一下。

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

实现效果:

360手机助手截图0914_23_03_01  360手机助手截图0914_23_04_02  360手机助手截图0914_23_04_01

本文介绍:

  • 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方法,打印如下右侧:

image

很明显,不加到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”,谢谢!

你可能感兴趣的:(SlidingMenu,addToBackStack,FragmentManager)