你的位置:首页 > 操作系统

[操作系统]toolbar中设定左上角按钮及其点击事件的顺序的原因(一)


作为一个老顽固,也不得不开始学习新技术了,这两天研究toolbar,网上找了些帖子,看完后对于toolbar设定的一些顺序不太清楚,比如设置setNavigationIcon,setNavigationOnClickListener必须在setSupportActionBar后面,原文关于这方面用“为什么在setSupportActionBar(toolbar);后面加入而不在前面,你可以加入到前面试试,虽然可以显示回退的图片,但是点击并没有调用该按钮的点击事件,而在setSupportActionBar(toolbar);后面设置点击才有反应。一定要记住,不然回退是不会起作用的。”但是没说为什么,让我感觉极其不爽,所以觉得需要找到真正原因,下面记录寻找过程:

 

经过尝试,发现setNavigationIcon可以在setSupportActionBar前面,如图1,

但是如果setNavigationOnClickListener在setSupportActionBar前面则点击事件没有反应,与原文中的表述一致,那么来查下原因,我先设想了下,什么情况下会出现这种情况,考虑再三,只想到了一种情况,就是在setSupportActionBar的时候系统重新设置了点击事件,把之前我设置的点击事件顶掉了,猜到可能的原因后就是验证的过程。

 

首先查看setSupportActionBar的源码,它是AppCompatActivity中的方法:

getDelegate()返回了一个AppCompatDelegate,再进去看下AppCompatDelegate的setSupportActionBar:

发现是个抽象的方法,那么就看一下getDelegate()是返回的AppCompatDelegate的哪个子类吧,看下getDelegate()方法:

没什么说得,看下create()方法:

这里看到根据版本的不同,会有三个子类,我们分别进去看看:

已经很明显的看清了继承关系,现在开始从AppCompatDelegateImplV14向AppCompatDelegateImplBase逐个类查找setSupportActionBar方法,结果发现AppCompatDelegateImplV14、AppCompatDelegateImplV11中都没有setSupportActionBar方法,该方法只存在于AppCompatDelegateImplV7中:

看到上图中红框部分,将toolbar当作构造参数传入了对象ToolbarActionBar,看下ToolbarActionBar中是怎么使用toolbar的:

看到上图中红框部分,将toolbar当作构造参数传入了对象ToolbarWidgetWrapper,只能继续看下ToolbarWidgetWrapper中是怎么使用toolbar的:

在ToolbarWidgetWrapper将toolbar缓存给了mToolbar,那么继续向下找mToolbar在此类中的使用情况:

到这里已经完全清楚了,在ToolbarWidgetWrapper的构造方法里,new了新的OnClickListener传进去,这里验证了我前面猜测的正确性,也就是setNavigationOnClickListener在setSupportActionBar前面设置则点击事件没有反应的原因是因为在setSupportActionBar的时候系统重新设置了点击事件,把之前设置的点击事件顶掉了。