android toolbar 居中中Fragment和toolbar?

&nbsp&#8250&nbsp&nbsp&#8250&nbsp
Android C Toolbar 上的 Navigation Drawer
ToolBar的基础知识请先阅读:在 Material Design 发布后,Google 也开始陆续更新了 Google app 的界面,让大家有个范例可以看。而过去大力推动的 actionbar 自然而然也成了众开发者观注的部份;其中的 up button(返回上一级) 的设置在前一篇所介绍的 Toolbar 也已看到。这边还未提到的一个部份是 material design 中有提到的人机交互效果,简言之,就是让使用者明显地感受到在操作 app 时,可以获得明显的回应,从而得到丰富地操作体验感;因此,在刚开始放出的几支 Google app 里,大家一定都有留意到开启 navigation drawer 时,up button 的旋转动画效果。先来看看效果:相信大家也都会很好奇这个效果要如何实现,会不会很麻烦?所幸,这个效果,被放进 support v7 之中,我们只要拿碛眉纯伞T诒酒薪窒铝屑父霾糠荩创蠹仪崴墒迪终庵中Ч础本篇所使用到的程式码,请到 Github 下载。1. 实作我们马上从
开始 (这份代码其实在
一文的自定义颜色一节完成的 ),在 activity_main.xml 中加入 DrawerLayout&RelativeLayout&xmlns:android=&/apk/res/android&
&&&&&&&&&&&&&&&&xmlns:tools=&/tools&
&&&&&&&&&&&&&&&&android:layout_width=&match_parent&
&&&&&&&&&&&&&&&&android:layout_height=&match_parent&
&&&&&&&&&&&&&&&&tools:context=&.MainActivity&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&android.support.v7.widget.Toolbar
&&&&android:id=&@+id/toolbar&
&&&&...&/&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&android.support.v4.widget.DrawerLayout
&&&&android:id=&@+id/drawer&
&&&&android:layout_height=&match_parent&
&&&&android:layout_width=&match_parent&
&&&&android:layout_below=&@+id/toolbar&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&!--&Content&--&
&&&&&RelativeLayout
&&&&&&android:layout_width=&match_parent&
&&&&&&android:layout_height=&match_parent&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&/RelativeLayout&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&!--&Side&Drawer&--&
&&&&&LinearLayout
&&&&&&android:id=&@+id/drawer_view&
&&&&&&android:layout_width=&@dimen/navdrawer_width&
&&&&&&android:layout_height=&match_parent&
&&&&&&android:layout_gravity=&start&
&&&&&&android:background=&#88FFFFFF&
&&&&&&android:orientation=&vertical&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&/LinearLayout&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&/android.support.v4.widget.DrawerLayout&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&/RelativeLayout&加入后,请记得将原本在 Toolbar 控件之前的 TextView 放到&!-- Content --& &部份,做 DrawerLayout 其中的热萁缑妫裨蛟谕欠湃 Content 界面的状r下,关闭侧边栏时,会发生「java.lang.NullPointerException: Attempt to invoke virtual method ‘android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()’ on a null object reference这样的错误讯息。在 drawer_view &中,要记得 layout_gravity 设定成 start &或是 left 。activity_main.xml 完整程式码请见 github。再来,就是到 MainActivity.java 中去实作 DrawerLayout,部份程式码如下:private&DrawerLayout&mDrawerL
private&ActionBarDrawerToggle&mDrawerT
protected&void&onCreate(Bundle&savedInstanceState)&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&//&打_&up&button
&&getSupportActionBar().setDisplayHomeAsUpEnabled(true);
&&mDrawerLayout&=&(DrawerLayout)&findViewById(R.id.drawer);
&&//&作&drawer&toggle&K放入&toolbar
&&mDrawerToggle&=&new&ActionBarDrawerToggle(this,&mDrawerLayout,&toolbar,&R.string.drawer_open,&R.string.drawer_close);
&&mDrawerToggle.syncState();
&&mDrawerLayout.setDrawerListener(mDrawerToggle);
}完成后,就可以看到如上方影像一样的效果了!完整程式码请见:2. Side Drawer一开始, & 中,其实是没有看到侧边栏的相关说明,一直到 2014.10 才以「Side Nav」之名,加述于导览文件之中。而这个定义中的 Side Nav 画面,其实跟原本在 actionbar 的阶段是不太一样的,drawer layout 会压在 toolbar 上,如下图:目前在 Google app 的界面中,还是以前一种为多,而现下 (2014.10) 如同 material &design 在 side nav 呈现的界面还不多。接下来就用
做为这个阶段的开始往下进行,需要调整就只有界面 (activity_main.xml) 的部份:&android.support.v4.widget.DrawerLayout
&&xmlns:android=&/apk/res/android&
&&xmlns:tools=&/tools&
&&android:id=&@+id/drawer&
&&android:layout_height=&match_parent&
&&android:layout_width=&match_parent&
&&tools:context=&.MainActivity&&
&&&!--&Content&--&
&&&RelativeLayout
&&&&android:layout_width=&match_parent&
&&&&android:layout_height=&match_parent&&
&&&&&android.support.v7.widget.Toolbar
&&&&&&android:id=&@+id/toolbar&
&&&&&&...&/&
&&&/RelativeLayout&
&&&!--&Side&Drawer&--&
&&&LinearLayout
&&&&android:id=&@+id/drawer_view&
&&&&android:layout_width=&@dimen/navdrawer_width&
&&&&android:layout_height=&match_parent&
&&&&android:layout_gravity=&start&
&&&&android:clickable=&true&
&&&&android:background=&#88FFFFFF&
&&&&android:orientation=&vertical&&
&&&/LinearLayout&
&/android.support.v4.widget.DrawerLayout&将 DrawerLayout 改到这个 layout 的 root 层,并将 toolbar 移到 content 的 layout 中,这样就可以达到这样的效果了。需要注意的是地方在 Side 的 layout 要设定 clickable 的属性设定为 true,否则会在侧边栏打开的状况下,还能按到位于界面下方的 up button。But!人生就是这个 but!在前一阵子,Google 的设计师为 Google I/O 2014 设计了另外一种样式出来,差异请见下图:嗯,简言之,状态栏是半透明的状态,而侧边栏可以被看到。要调整的地方有二,一在 layout C activity_main.xml:&android.support.v4.widget.DrawerLayout
&&android:fitsSystemWindows=&true&
&&&!--&Content&--&
&&&!--&Side&Drawer&--&
&&&LinearLayout
&&&&android:fitsSystemWindows=&true&
&&&/LinearLayout&
&/android.support.v4.widget.DrawerLayout&在 root 层的 drawer layout 跟 side drawer 的 layout 各别加上 android:fitsSystemWindows=&true& 这个属性另外一个要改的地方是在 v21/styles.xml&style&name=&AppTheme&&parent=&AppTheme.Base&&
&&&!--Status&bar&color--&
&&&item&name=&android:statusBarColor&&#&/item&
&/style&加入一个有透明度的色码给 android:statusBarColor 这个状态列颜色设定属性。这样就可以完成这个阶段的程式了。完整程式码请见:3. 其他议题Navigation icon 切换的效果,除了旋转以外,还有另外一种效果,请看下方的影像:3.1 Navigation icon effect左上角的切换效果变成线条的的聚合,同时 icon 的颜色也被改为黑色,这个设定只要在 /res/values/styles.xml 做如下设定&style&name=&AppTheme.Base&&parent=&Theme.AppCompat&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&!--⑿录尤氲娘L格&AppTheme.MyDrawerStyle&O定o&drawerArrowStyle&@傩--&
&&&item&name=&drawerArrowStyle&&@style/AppTheme.MyDrawerArrowStyle&/item&
&!--加入一新的&navigation&drarwer&的L格--&
&style&name=&AppTheme.MyDrawerArrowStyle&&parent=&Widget.AppCompat.DrawerArrowToggle&&
&&&!--&spinBars&傩栽O定&false--&
&&&item&name=&spinBars&&false&/item&
&&&!--O定&drawer&arrow&的色--&
&&&item&name=&color&&@android:color/black&/item&
&/style&先加入针对 navigation icon 设定的风格: AppTheme.MyDrawerArrowStyle ,其继承自 Widget.AppCompat.DrawerArrowToggle 这个风格。以本范例来说,这个风格e设定了两个属性: & &spinBars & & & &旋转效果 & & & &false。由此可之,其预设的旋转效果预设值就是 true 了。 & &color & & & &设定 navigation icon 的颜色。增加后,再回到 AppTheme.Base 风格中,将此风格设定给 drawerArrowStyle 即可看到效果了。3.2 Shadows在影像中,大家应该可以看到,这个范例中还有一处跟之前不同了,内容为 Hello world! 的 TextView 变成黑色了!哦!当然不是要为各位介绍这个以前就有属性。要请各位留意的是在 TextView 周围有一圈淡淡的影子,还有在 Toolbar 也因为下方的影子,看起来较有立体感。而这也就是在 Material design 中有提到的其中一个部份:。在过去这个效果需要自己去设定 drawable,现在只要设定个属性即可。请到 activity_main.xml 中&!--&Content&--&
&RelativeLayout
&&android:layout_width=&match_parent&
&&android:layout_height=&match_parent&&
&&&android.support.v7.widget.Toolbar
&&&&android:elevation=&10dp&
&&&&...&&/&
&&&TextView
&&&&android:elevation=&10dp&
&&&&android:background=&@android:color/black&
&/RelativeLayout&最主要就是针对 android:elevation 这个属性设定,而这个属性的意义也如同其字面的意义,他是在承述相较于底层的高度而被创造出来的阴影。而另外,在这段程式码中,特别将 TextView 中的 android:background 也列出来的原因,就是要让大家知道,android:elevation 这个属性要能够生效,该介面元件的背景属性也需要设定哦!完整程式码请见:4. 一点想法新的 navigation drawer 在 material design 的 side nav e有著跟过去不同的样式,而在 Google app 中,包含文中提到那种新的呈现样式算来,共有三重风格。这应该也意谓著,以 Google 在 side nav 在 android app 的呈现上,给予了这些弹性在。换句话说,这样看来,目前看到的这三种样式在 android app 上来看,都可以算是 material design。也许有人会问,那导览文件是写好玩的吗?以个人的观点来看,那个的确是一个规范,是 Google 想要在不同的平台上有一个共通的范畴得以依循。因此,相信未来在 Google 的产品中,于 web、iOS 以及其他装置的介面,都会以 material design 做为标准,而设计出统一的 Google app 的体验。而在 android 装置上,嘿嘿…毕竟是 Google 定义的嘛~那自然这部份的弹性就多于其他平台喽。所以,私以为就别太过纠结于导览文件上的定义,只要符合目前所看到的三种样式,应该都可以被视 android 装置上的 material design 啦。大家也可以放宽心的运用这三种样式去做 android app 的设计喽。当然,以上纯粹个人观点,不代表官方立场,除非有 Google 的人在本篇中给予留言,做认证喽 :最後,附上本篇所有例的,大家多多指教D。
上一篇: android使用java作为其开发环境。java的跨平台和垃圾回收机制已经帮助我们解决了底层的一些问题。但是尽管有了垃圾回收机制,在开发android的时候仍然时不时的遇到out of memory的问题,这个时候我们不禁要问,垃圾回收机器去哪儿了? 我们主要讲的是handler
下一篇: 因为想要将本网站上的开源代码直接做成一个能显示效果的app,决定摸索下android的插件开发,发现只有两个开源的插件系统可选: AndroidDynamicLoader dynamic-load-apk 因为第一个只允许在fragment的基础上开发插件,第二个没有此限制并且是国人开发,文档比点击阅读原文
打造安卓App丝滑的操作体验--Fragment深入使用和封装之道
3月16日 发布,来源:
想让App有丝滑般的切换速度和顺畅的体验么?那就放开Activity,使用Fragment来展示UI页面吧
Github 上列举了一些列安卓开发最佳实践建议,其中对Fragment使用做了一些陈述(),我表示赞同。
最近项目需要新增了一个功能模块,我引入了一个Activity,多个fragment的方式来组织UI,这个过程有了一些收获。
对fragment的操作,我使用support v4包下的,FragmentManager和FragmentTransaction这两个类。
如何启动一个Fragment
replace方式
这里我没有用Activity下的getSupportFragmentManager得到了FragmentManager来替换Fragment,而是选择使用fragment下的getChildFragmentManager()获取FragmentManager。
放在基类BasicActivity里,
resId 被替换的布局ID
fragmentTab 新的Fragment名
arguments 传入新的Fragment的Bundle
isAddToBack 是否加入回退栈
private void replaceOneFragment(@IdRes int resId, String fragmentTab, Bundle arguments, boolean isAddToBack) {
int childrenFragmentContainerResID = ((BasicFragment) mCurrentFragment).getChildrenFragmentContainerResID();
int layoutId = resId &= 0 ? childrenFragmentContainerResID : resId;
if (layoutId == -1) {
throw new IllegalStateException("You should overwrite getChildrenFragmentContainerResID from BasicFragment");
FragmentManager manager = mCurrentFragment.getChildFragmentManager();
if (manager != null) {
FragmentTransaction transaction = manager.beginTransaction();
transaction
.setCustomAnimations(R.anim.right_enter, R.anim.left_exit, R.anim.left_enter, R.anim.right_exit)
.replace(layoutId, fragmentProvider(fragmentTab, arguments), fragmentTab);
if (isAddToBack) {
transaction.addToBackStack(fragmentTab);
mitAllowingStateLoss();
getChildrenFragmentContainerResID(),该方法在BasicFragment里,用来获取要替换的布局ID
BasicActivity里,fragmentProvider(),Fragment提供者
add/show/hide显示Fragment(支持SingleTask启动Fragment)
private void showOneFragment(String fragmentTab, Bundle arguments, boolean isAddBackStack, LaunchMode launchMode) {
FragmentManager manager = getSupportFragmentManager();
if (manager == null) {
Fragment fragmentByTag = manager.findFragmentByTag(fragmentTab);
if (fragmentByTag != null && launchMode == LaunchMode.SINGLE_ENHANCEMENT) {
popMultipleBackStack(fragmentTab, arguments);
FragmentTransaction transaction = manager.beginTransaction();
transaction.setCustomAnimations(R.anim.right_enter, R.anim.left_exit, 0, 0);
List&Fragment& fragments = manager.getFragments();
if (fragments != null && fragments.size() & 0) {
for (Fragment f : fragments) {
if (f != null) {
transaction.hide(f);
if (fragmentByTag == null) {
mCurrentFragment = fragmentProvider(fragmentTab, arguments);
mFragmentBackDeque.push(fragmentTab);
transaction.add(getFragmentContainerResID(), mCurrentFragment, fragmentTab);
if (isAddBackStack) {
transaction.addToBackStack(fragmentTab);
mitAllowingStateLoss();
if (!(fragmentByTag instanceof BasicFragment)) {
throw new ClassCastException("fragment must extends BasicFragment");
if (arguments != null) {
setSupportBackStackArguments(arguments);
switch (launchMode) {
case STANDARD:
mFragmentBackDeque.push(fragmentTab);
case SINGLE:
synchronizeFragmentBackDequeWhenSingleLaunchMode(fragmentTab);
BasicFragment basicFragment = (BasicFragment) fragmentByT
mCurrentFragment = fragmentByT
basicFragment.setSupportArguments(arguments);
transaction.show(fragmentByTag);
mitAllowingStateLoss();
public enum LaunchMode {
SINGLE_ENHANCEMENT,
popMultipleBackStack()实现一次弹出多个Fragment
在隐藏当前所有fragment操作,特别需要在遍历时,做个非空判断,
for (Fragment f : fragments) {
if (f != null) {
transaction.hide(f);
这样做,是因为Fragment出栈后,会出现栈内顺序不正确的bug,详看,一文中关于多个Fragment同时出栈的深坑BUG这一部分的内容。
synchronizeFragmentBackDequeWhenSingleLaunchMode()单例模式下,管理自维护的Fragment后退栈
mFragmentBackDeque是自维护回退管理队列
后退键监听管理
使用Fragment组织UI后,返回上一个页面的逻辑有了变化。如果遇到之前replace替换了,则先从该fragment的FragmentManager里恢复原来的被替换的fragment,没有,则把之前hide状态的Fragment重新show显示出来,这个过程需要用了队列自己来维护回退
public void onBackPressed() {
if (mFragmentBackDeque == null || mCurrentFragment == null) {
int childStackEntryCount = mCurrentFragment.getChildFragmentManager().getBackStackEntryCount();
if (childStackEntryCount & 0) {
mCurrentFragment.getChildFragmentManager().popBackStackImmediate();
if (mFragmentBackDeque.size() &= 2) {
showOneFragmentOnBackPressed();
showOneFragmentOnBackPressed()实现返回键显示特定Tag的Fragment
同时,如果需要,我们可以给FragmentManager添加OnBackStackChangedListener,监听FragmentManager回退栈成员数量的变化,具体使用见文末的代码
还有一种思路,View提供了setOnKeyListener(OnKeyListener onKeyListener),用OnKeyListener来监听后退健。
Fragment入参管理
第一次启动Fragment,走的是fragment生命周期方法,之后启动fragment从hide状态重新show时,不走Fragment生命周期方法,而是调用onHiddenChanged(boolean hidden)方法。因此,在这两种场景下支持给fragment传入参数,并且做到每次显示fragment,都能拿到最新的入参bundle。
我在BasicFragment设计如下:
(Bundle arguments){
public void onCreate(@Nullable Bundle savedInstanceState) {
.onCreate(savedInstanceState);
(getArguments());
(boolean hidden) {
.onHiddenChanged(hidden);
(!hidden){
(getSupportArguments());
这样,新的Fragmnet在继承BasicFragment时,只需要重新parseArguments()即可
Toolbar管理
项目中使用Toolbar,用BasicFragmentWithToolbar来负责Toolbar的设置逻辑
BasicFragmentWithToolbar类里的核心代码
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
configureToolbar();
protected void configureToolbar() {
super.configureToolbar();
int stackEntryCount = getChildFragmentManager().getBackStackEntryCount();
if (stackEntryCount & 0) {
FragmentManager.BackStackEntry stackEntry = getChildFragmentManager().getBackStackEntryAt(stackEntryCount - 1);
String fragmentTab = stackEntry.getName();
BasicFragmentWithToolbar fragmentByTag = (BasicFragmentWithToolbar) getChildFragmentManager().findFragmentByTag(fragmentTab);
if (fragmentByTag != null) {
fragmentByTag.setupToolbar();
setupToolbar();
protected void setupToolbar() {
mToolbar.setNavigationIcon(R.drawable.icon_header_left);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getAttachActivity().onBackPressed();
如何使用上述的Fragment封装
我举个例子,我建一个BillContainerActivity,来作为Bill相关的Fragment容器,代码如下
public class BillContainerActivity extends BasicActivity {
private static final String TAG = "BillContainerActivity";
@Bind(R.id.frame_activity_order_body)
FrameLayout mOrderB
public static Intent getCallingIntent(Activity activity){
Intent intent = new Intent(activity,BillContainerActivity.class);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initializeShow();
private void initializeShow() {
showOneFragment(BillHomeFragment.class.getSimpleName(),true);
protected BasicFragment fragmentProvider(String fragmentTab, Bundle arguments) {
BasicFragment currentF
if(BillHomeFragment.class.getSimpleName().equals(fragmentTab)){
currentFragment = BillHomeFragment.newInstance();
else if(BillProcessFragment.class.getSimpleName().equals(fragmentTab)){
currentFragment = BillProcessFragment.newInstance(arguments);
else if(BillStructureFragment.class.getSimpleName().equals(fragmentTab)){
currentFragment = BillStructureFragment.newInstance(arguments);
else if(AdjustBillDetailFragment.class.getSimpleName().equals(fragmentTab)){
currentFragment = AdjustBillDetailFragment.newInstance(arguments);
else if(BrokerageDetailFragment.class.getSimpleName().equals(fragmentTab)){
currentFragment = BrokerageDetailFragment.newInstance(arguments);
else if(InvoiceDetailFragment.class.getSimpleName().equals(fragmentTab)){
currentFragment = InvoiceDetailFragment.newInstance(arguments);
else if(InvoiceListFragment.class.getSimpleName().equals(fragmentTab)){
currentFragment = InvoiceListFragment.newInstance(arguments);
currentFragment = BillHomeFragment.newInstance();
return currentF
protected int getFragmentContainerResID() {
return R.id.frame_activity_order_
protected int getLayoutResID() {
return R.layout.activity_bill_
说明会发现作为Fragment容器的BillContainerActivity,代码量很少,主要做两件事
初始化显示Fragment
实现fragmentProvider方法,该方法把这个容器所需的Fragment构造出来
再次使用Fragment,有了更深入的理解。代码不是很多就不放在github上,直接贴出来了,欢迎交流。
完整代码展示:
BasicFragment
public abstract class BasicFragment extends Fragment {
private BasicActivity mA
private int mLastChildStackEntryCount = 0;
private int mLastSupportStackEntryCount = 0;
private Bundle mSupportA
private CompositeSubscription mCompositeS
public void onAttach(Context context) {
super.onAttach(context);
mActivity = (BasicActivity)
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
parseArguments(getArguments());
setHasOptionsMenu(true);
getChildFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
public void onBackStackChanged() {
int currentStackEntryCount = getChildFragmentManager().getBackStackEntryCount();
if(currentStackEntryCount - mLastChildStackEntryCount & 0){
configureToolbar();
onChildBackPressed();
mLastChildStackEntryCount = currentStackEntryC
final FragmentManager manager = mActivity.getSupportFragmentManager();
manager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
public void onBackStackChanged() {
int currentStackEntryCount = manager.getBackStackEntryCount();
if(currentStackEntryCount - mLastSupportStackEntryCount & 0){
onSupportBackPressed(getAttachActivity().getSupportBackStackArguments());
mLastSupportStackEntryCount = currentStackEntryC
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = LayoutInflater.from(getContext()).inflate(getLayoutResID(),container,false);
ButterKnife.bind(this,view);
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if(!hidden){
parseArguments(getSupportArguments());
protected void parseArguments(Bundle arguments){
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
public void onDestroy() {
if(mCompositeSubscription != null){
mCompositeSubscription.unsubscribe();
super.onDestroy();
private CompositeSubscription getCompositeSubscription(){
if(mCompositeSubscription == null){
mCompositeSubscription = new CompositeSubscription();
return mCompositeS
errorAction1
protected &T& void addSubscription(Class&T& tClass, Action1&T& action1, Action1&Throwable& errorAction1){
getCompositeSubscription()
.add(RxBus.getInstance().toSubscription(tClass, action1,errorAction1));
public BasicActivity getAttachActivity(){
private Bundle getSupportArguments() {
return mSupportA
public void setSupportArguments(Bundle supportArguments) {
mSupportArguments = supportA
protected void configureToolbar() {
protected void onChildBackPressed(){
protected void onSupportBackPressed(Bundle bundle){
替换的布局ID
protected int getChildrenFragmentContainerResID() {
return -1;
protected abstract @LayoutRes int getLayoutResID();
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
MPermissions.onRequestPermissionsResult(this,requestCode,permissions,grantResults);
BasicFragmentWithToolbar
public abstract class BasicFragmentWithToolbar extends BasicFragment {
private static final String TAG = "BasicFragmentWithToolbar";
@Bind(R.id.toolbar_include)
Toolbar mT
@Bind(R.id.tv_include_header_title)
TextView mTvHeaderT
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
initToolbar();
setupToolbar();
adaptStatusBar();
private void adaptStatusBar() {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
if (mToolbar != null) {
WindowManager.LayoutParams localLayoutParams = getAttachActivity().getWindow().getAttributes();
localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
int toolbarHeight = (int)getResources().getDimension(R.dimen.tool_bar_height_adapt);
ViewGroup.LayoutParams layoutParams = mToolbar.getLayoutParams();
layoutParams.height = toolbarH
int toolbarPaddingTop = (int) getResources().getDimension(R.dimen.tool_bar_padding_top);
mToolbar.setPadding(0, toolbarPaddingTop, 0, 0);
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
configureToolbar();
private void initToolbar() {
mToolbar.setTitle("");
mToolbar.setSubtitle("");
getAttachActivity().setSupportActionBar(mToolbar);
protected void configureToolbar() {
super.configureToolbar();
int stackEntryCount = getChildFragmentManager().getBackStackEntryCount();
if (stackEntryCount & 0) {
FragmentManager.BackStackEntry stackEntry = getChildFragmentManager().getBackStackEntryAt(stackEntryCount - 1);
String fragmentTab = stackEntry.getName();
BasicFragmentWithToolbar fragmentByTag = (BasicFragmentWithToolbar) getChildFragmentManager().findFragmentByTag(fragmentTab);
if (fragmentByTag != null) {
fragmentByTag.setupToolbar();
setupToolbar();
protected void setupToolbar() {
mToolbar.setNavigationIcon(R.drawable.icon_header_left);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getAttachActivity().onBackPressed();
public void hideToolbar() {
mToolbar.setVisibility(View.GONE);
public void setToolbarVisibilty(int visibilty) {
mToolbar.setVisibility(visibilty);
public void setHeaderTitle(String titleContent) {
mTvHeaderTitle.setText(titleContent);
public void setHeaderTitle(@StringRes int titleResID) {
mTvHeaderTitle.setText(titleResID);
public void setNavigationIcon(@DrawableRes int resID) {
mToolbar.setNavigationIcon(resID);
public void setupToolbar(@DrawableRes int leftResID, String titleContent) {
mToolbar.setNavigationIcon(leftResID);
setHeaderTitle(titleContent);
public Toolbar getToolbar() {
protected abstract
@LayoutRes
int getLayoutResID();
BasicActivity
public abstract class BasicActivity extends AppCompatActivity {
private static final String TAG = "BasicActivity";
private Deque&String& mFragmentBackDeque = new ArrayDeque&&();
private Fragment mCurrentF
private Bundle mSupportBackStackA
private Handler mH
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResID());
ButterKnife.bind(this);
protected void onDestroy() {
ButterKnife.unbind(this);
super.onDestroy();
public void replaceOneFragment(String fragmentTab) {
replaceOneFragment(0, fragmentTab, null, true);
public void replaceOneFragment(String fragmentTab, Bundle bundle) {
replaceOneFragment(0, fragmentTab, bundle, true);
public void replaceOneFragment(@IdRes int resId, String fragmentTab) {
replaceOneFragment(resId, fragmentTab, null, true);
public void replaceOneFragment(@IdRes int resId, String fragmentTab, Bundle bundle) {
replaceOneFragment(resId, fragmentTab, bundle, true);
public void replaceOneFragment(String fragmentTab, boolean isAddToBack) {
replaceOneFragment(0, fragmentTab, null, isAddToBack);
public void replaceOneFragment(@IdRes int resId, String fragmentTab, boolean isAddToBack) {
replaceOneFragment(resId, fragmentTab, null, isAddToBack);
public void replaceOneFragment(String fragmentTab, Bundle bundle, boolean isAddToBack) {
replaceOneFragment(0, fragmentTab, bundle, isAddToBack);
resId 被替换的布局ID
fragmentTab 新的Fragment名
arguments 传入新的Fragment的Bundle
isAddToBack 是否加入回退栈
private void replaceOneFragment(@IdRes int resId, String fragmentTab, Bundle arguments, boolean isAddToBack) {
int childrenFragmentContainerResID = ((BasicFragment) mCurrentFragment).getChildrenFragmentContainerResID();
int layoutId = resId &= 0 ? childrenFragmentContainerResID : resId;
if (layoutId == -1) {
throw new IllegalStateException("You should overwrite getChildrenFragmentContainerResID from BasicFragment");
FragmentManager manager = mCurrentFragment.getChildFragmentManager();
if (manager != null) {
FragmentTransaction transaction = manager.beginTransaction();
transaction
.setCustomAnimations(R.anim.right_enter, R.anim.left_exit, R.anim.left_enter, R.anim.right_exit)
.replace(layoutId, fragmentProvider(fragmentTab, arguments), fragmentTab);
if (isAddToBack) {
transaction.addToBackStack(fragmentTab);
mitAllowingStateLoss();
fragmentTab
public void showOneFragment(String fragmentTab) {
showOneFragment(fragmentTab, null, true, STANDARD);
fragmentTab
isAddToStack 第一次显示时,是否加入回退栈
public void showOneFragment(String fragmentTab, boolean isAddToStack) {
showOneFragment(fragmentTab, null, isAddToStack, STANDARD);
fragmentTab
public void showOneFragment(String fragmentTab, Bundle arguments) {
showOneFragment(fragmentTab, arguments, true, STANDARD);
public void showOneFragment(String fragmentTab, Bundle arguments, LaunchMode launchMode) {
showOneFragment(fragmentTab, arguments, true, launchMode);
fragmentTab
Fragment标签名
传入Fragment的参数Bundle
isAddBackStack 是否加入FragmentManager回退栈
launchMode
启动模式 分为: STANDARD,SINGLE,SINGLE_ENHANCEMENT
private void showOneFragment(String fragmentTab, Bundle arguments, boolean isAddBackStack, LaunchMode launchMode) {
FragmentManager manager = getSupportFragmentManager();
if (manager == null) {
Fragment fragmentByTag = manager.findFragmentByTag(fragmentTab);
if (fragmentByTag != null && launchMode == LaunchMode.SINGLE_ENHANCEMENT) {
popMultipleBackStack(fragmentTab, arguments);
FragmentTransaction transaction = manager.beginTransaction();
transaction.setCustomAnimations(R.anim.right_enter, R.anim.left_exit, 0, 0);
List&Fragment& fragments = manager.getFragments();
if (fragments != null && fragments.size() & 0) {
for (Fragment f : fragments) {
if (f != null) {
transaction.hide(f);
if (fragmentByTag == null) {
mCurrentFragment = fragmentProvider(fragmentTab, arguments);
mFragmentBackDeque.push(fragmentTab);
transaction.add(getFragmentContainerResID(), mCurrentFragment, fragmentTab);
if (isAddBackStack) {
transaction.addToBackStack(fragmentTab);
mitAllowingStateLoss();
if (!(fragmentByTag instanceof BasicFragment)) {
throw new ClassCastException("fragment must extends BasicFragment");
if (arguments != null) {
setSupportBackStackArguments(arguments);
switch (launchMode) {
case STANDARD:
mFragmentBackDeque.push(fragmentTab);
case SINGLE:
synchronizeFragmentBackDequeWhenSingleLaunchMode(fragmentTab);
BasicFragment basicFragment = (BasicFragment) fragmentByT
mCurrentFragment = fragmentByT
basicFragment.setSupportArguments(arguments);
transaction.show(fragmentByTag);
mitAllowingStateLoss();
fragment替换的布局ID
protected int getFragmentContainerResID() {
return -1;
fragmentTab Fragment标签
arguments 传入Fragment的参数
protected BasicFragment fragmentProvider(String fragmentTab, Bundle arguments) {
return null;
private void showOneFragmentOnBackPressed() {
mFragmentBackDeque.pop();
String fragmentTab = mFragmentBackDeque.peek();
FragmentManager manager = getSupportFragmentManager();
if (manager != null) {
FragmentTransaction transaction = manager.beginTransaction();
transaction.setCustomAnimations(R.anim.left_enter, R.anim.right_exit, 0, 0);
List&Fragment& fragments = manager.getFragments();
for (Fragment f : fragments) {
if (f != null) {
transaction.hide(f);
Fragment fragmentByTag = manager.findFragmentByTag(fragmentTab);
if (fragmentByTag != null) {
mCurrentFragment = fragmentByT
transaction.show(fragmentByTag);
mitAllowingStateLoss();
popFlag 0 弹出不包括tag所指的Fragment;1 表示弹出包括当前tag的fragment
回退栈 传输参数
public void popMultipleBackStack(String tag, int popFlag, Bundle bundle) {
if (bundle != null) {
setSupportBackStackArguments(bundle);
if (mFragmentBackDeque.contains(tag)) {
String peekElement = mFragmentBackDeque.peek();
while (!tag.equals(peekElement)) {
if (mFragmentBackDeque.isEmpty()) {
mFragmentBackDeque.pop();
peekElement = mFragmentBackDeque.peek();
if (popFlag == 1) {
if (!mFragmentBackDeque.isEmpty()) {
mFragmentBackDeque.pop();
FragmentManager manager = getSupportFragmentManager();
manager.popBackStackImmediate(tag, popFlag);
bundle 回退栈 传输参数
private void popMultipleBackStack(String tag, Bundle bundle) {
if (bundle != null) {
setSupportBackStackArguments(bundle);
synchronizeFragmentBackDequeWhenSingleLaunchMode(tag);
FragmentManager manager = getSupportFragmentManager();
manager.popBackStackImmediate(tag, 0);
reorderAvailIndicesToFixBug();
private void reorderAvailIndicesToFixBug(){
if(mHandler == null) {
mHandler = new Handler(getMainLooper());
mHandler.post(new Runnable() {
public void run() {
FragmentTransactionBugFixHack.reorderIndices(getSupportFragmentManager());
private void synchronizeFragmentBackDequeWhenSingleLaunchMode(String tag) {
if (mFragmentBackDeque.contains(tag)) {
String peekElement = mFragmentBackDeque.peek();
while (!tag.equals(peekElement)) {
if (mFragmentBackDeque.isEmpty()) {
mFragmentBackDeque.pop();
peekElement = mFragmentBackDeque.peek();
public void onBackPressed() {
if (mFragmentBackDeque == null || mCurrentFragment == null) {
int childStackEntryCount = mCurrentFragment.getChildFragmentManager().getBackStackEntryCount();
if (childStackEntryCount & 0) {
mCurrentFragment.getChildFragmentManager().popBackStackImmediate();
if (mFragmentBackDeque.size() &= 2) {
showOneFragmentOnBackPressed();
public Fragment getCurrentFragment() {
return mCurrentF
public Deque&String& getFragmentBackDeque() {
return mFragmentBackD
public Bundle getSupportBackStackArguments() {
if (mSupportBackStackArguments == null) {
mSupportBackStackArguments = new Bundle();
return mSupportBackStackA
public void setSupportBackStackArguments(Bundle supportBackStackArguments) {
this.mSupportBackStackArguments = supportBackStackA
protected abstract
@LayoutRes
int getLayoutResID();
public enum LaunchMode {
SINGLE_ENHANCEMENT,
相关阅读资料
特别鸣谢:YoKey系列
(需自备梯子)
明天提醒我
我要该,理由是:
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)}

我要回帖

更多关于 android toolbar 阴影 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信