這兩天研究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的時候系統重新設置了點擊事件,把之前設置的點擊事件頂掉了。