Toolbar菜单动态改变item的图标(二)

来源:互联网 发布:复星金服java招聘 编辑:程序博客网 时间:2024/05/19 09:01

之前发过一篇关于Activity中的Toolbar在搭配Fragment使用的时候动态切换item图标的文章,但是随着学习的深入,需求的复杂,以前的那种解决方法在我看来已经越来越不适用了,于是我决定用新的方法解决这个问题,并写了这篇文章作为上一篇文章的补充,而上一篇文章我也将保留,作为我学习之路上的一个坑。

在之前的解决方法里,我们在初始化Activity的时候第一个Fragment也会初始化,所以我当时把第一个Fragment对应的Toolbar显示的标题以及菜单的图标都在Activity中做了初始化(Toolbar的title是在Activity的onCreate()方法中初始化,图标则是在Menu的布局文件中。),而当启动第二个Fragment覆盖了第一个Fragment之后,title和图标的改变我是通过onOptionsItemSelected(MenuItem item)方法来完成的。当最上层的第二个Fragment销毁的时候,title和图标又要返回与第一个Fragment相对应的状态,于是我监听了Menuitem的android.R.id.home的点击事件,在里面进行判断当前最顶层和用户交互的Fragment是谁,从而决定是销毁Fragment还是销毁Activity,以及更改Toolbar的title以及上面按钮的图标。详情可以参照我之前的那篇文章。

我现在发现,我这样写会导致代码异常杂乱,Toolbar显示信息的定义的相关代码到处都是,可读性极差,而且,每次启动新的Fragment的按钮并不一定都是Toolbar上面的,这样就导致,如果一个Activity如果出现三个或三个以上的Fragment的话,代码将会更混乱,甚至如果把代码交给第二个人将会变的完全不可读。今天我们就用一个新方法来解决这个问题。

首先,和之前一样,Activity中要设置一个状态变量status来表示当前和用户交互的是哪一个Fragment,每个Fragment用一个常量表示。然后,如果要Fragment拥有模拟返回栈的效果,就必须在把它添加到Activity中的时候有这样一行代码:

transaction.addToBackStack(null); 

这行代码我之前也写了,但是完全没有发挥出它的作用。接着,只要你添加了这行代码,你就会发现,每次你点击back键,如果Activity中有好几个Fragment的话,就会一个一个的移除Fragment,直到第一个Fragment位于栈顶的时候再点back键才会销毁Activity,查阅资料我们直到,按下back键的时候,执行的方法不是finish(),而是onBackPress(),这个方法会判定处理Fragment的返回栈模拟的情况。于是,我们只需要在onOptionsItemSelected(MenuItem item)的android.R.id.home这个item的事件监听中调用onBackPress()方法,这样,Toolbar最左边的返回键也可以变得和back键一样。接着,我们要把所有修改Toolbar显示信息的代码集中到一起,这样易于阅读和管理。我们不再在onOptionsItemSelected(MenuItem item)中修改Toolbar,而是全部集中到onPrepareOptionsMenu(Menu menu)方法中,我们知道,只要重写这个方法,用本Activity的实例去调用invalidateOptionsMenu()这个方法,onPrepareOptionsMenu(Menu menu)方法就会被执行一次。这样的话,我们在每个和Activity相关联的Fragment中就必须得到一个Activity的实例,我们就可以这样写(假如Activity的名字叫做MainActivity):

MainActivity mActivity = (MainActivity) getActivity();

这行代码可以写在Fragment的初始化的方法中,只要是在onStart()执行之前就可以。接着,我们要重写Fragment的onStart方法:

@Overridepublic void onStart() {    MainActivity.status = MainActivity.XXX    mActivity.invalidateOptionsMenu();}

之所以写在onStart()方法里是因为,这样无论是添加一个Fragment,还是移除一个Fragment,都能让用户可见的Fragment执行这个方法从而修改Toolbar;

当然onPrepareOptionsMenu(Menu menu)方法中有一个判定status值的语句,从而判定方法被执行时,它是在哪个Fragment中的onStart()被调用的,从而设置正确的Toolbar布局,以及Toolbar显示的title。

用了以上的这个方法后,无论Activity中有多少个Fragment,都能以简单易懂的方式,修改Toolbar,其实这个方法主要的核心就是:

1.Fragment返回栈模拟,以及onBackPress()方法的调用

2.利用onPrepareOptionsMenu(Menu menu)方法能在任何有Activity实例的地方调用的特点,将所有修改Toolbar的代码集中于此,而不要把他们散布到其他和Menu有关的回调方法中或者Activity以及Fragment生命周期的回调方法中,或是和添加以及移除Fragment有关的方法中。

3.在Fragment中获取和它关联的Activity的实例,并强制转型至那个具体的Activity类型,getActivity()只是返回最原始的Activity类型,这样会让你不能用这个实例调用你的Activity中的方法。


这篇文章就到这里,我只是大致简述了思想,但是没有像之前那篇文章一样写各种各样举例说明的代码,主要是,举例说明太占篇幅,而且不少地方和之前文章也有重复之处,本文作为之前的补充说明就不再大段举例了,相信大家能够读懂。


2017.03.03更新:

鉴于这个主题的第一篇文章完全是踩坑,而本文作为第二篇并没有一步接一步的详细教程,因此,等我有时间,我会再写最后一篇本主题的详细教程。
1 0
原创粉丝点击