Toolbar的Title與NavigationIcon距離異常

問題描述

當我將Support包由V22.2.0升級到V24.0.0的版本之后逼蒙,發(fā)現(xiàn)原來正常顯示的Toolbar顯示異常。前提是我并沒有修改任何代碼腰涧。請看下圖

NavigationIcon和Title的距離正確
距離顯示正確.jpg
NavigationIcon和Title的距離出現(xiàn)了異常
距離顯示異常.jpg

問題的解決方法

解決辦法很簡單臣镣,見代碼
為了方便起見,先定義一個Toolbar的Theme

<style name="NoSpaceActionBarTheme" parent="Base.Widget.AppCompat.Toolbar">
    <item name="contentInsetStart">0dp</item>
    <item name="contentInsetStartWithNavigation">0dp</item>
</style>

如果在布局文件中添加Toolbar的話可以通過增加style來實現(xiàn)竿报,代碼如下

<android.support.v7.widget.Toolbar
            style="@style/NoSpaceActionBarTheme"
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:navigationIcon="?attr/homeAsUpIndicator"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

如果定義過Activity的Theme是ActionBar的話,可以在Theme的定義中加上一句代碼参歹,如下

<style name="ActionBarTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="toolbarStyle">@style/NoSpaceActionBarTheme</item>
</style>

問題原因

為了搞明白為什么Support包從V22.2.0版本升級到V24.0.0就會出現(xiàn)這樣的問題仰楚,還是需要翻看Toolbar的源代碼,OK犬庇,我們直接看Toolbar的代碼(V24.0.0包中)僧界,順便說一下Toolbar是在appcompact-v7包下面

//用到的主要屬性名稱為contentInsetStart
private final RtlSpacingHelper mContentInsets = new RtlSpacingHelper();
//對應的屬性名稱為contentInsetStartWithNavigation
private int mContentInsetStartWithNavigation;

mContentInsets 這個成員變量和mContentInsetStartWithNavigation用來控制NavigationIcon和Title之間的距離的,我們接著看這兩個變量是如何影響這個距離的

最主要的代碼在Toolbar中的onLayout方法中臭挽,下面我摘取主要代碼來說明

final int paddingLeft = getPaddingLeft();
//首先是獲取系統(tǒng)的偏移量    
int left = paddingLeft;
//這段代碼用來計算Navigation的Layout
if (shouldLayout(mNavButtonView)) {
        if (isRtl) {
            right = layoutChildRight(mNavButtonView, right, collapsingMargins,
                    alignmentHeight);
        } else {
            //計算完之后left的距離為paddingLeft+mNavButtonView的寬度+mNavButtonView自身的偏移量
            left = layoutChildLeft(mNavButtonView, left, collapsingMargins,
                    alignmentHeight);
        }
    }
//核心的方法捂襟,返回就是那個讓距離錯誤的值
final int contentInsetLeft = getCurrentContentInsetLeft();
//left會從之前的left值也就是計算過Navigation的距離之后 和contentInsetLeft比較,取最大值
left = Math.max(left, contentInsetLeft);
...接下來計算Title的布局的時候左邊距就是用的這個left

我們來看看getCurrentContentInsetLeft()這個方法

public int getCurrentContentInsetLeft() {
    return ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL
            ? getCurrentContentInsetEnd()
            : getCurrentContentInsetStart();
}

因為我們是從左向右顯示所以會調(diào)用getCurrentContentInsetStart()這個方法欢峰,我們繼續(xù)看這個方法

public int getCurrentContentInsetStart() {
    return getNavigationIcon() != null
            ? Math.max(getContentInsetStart(), Math.max(mContentInsetStartWithNavigation, 0))
            : getContentInsetStart();
}

首先我們是有NavigationIcon的所以會走這個分支

Math.max(getContentInsetStart(), Math.max(mContentInsetStartWithNavigation, 0))

其中Math.max(mContentInsetStartWithNavigation, 0)返回的就是mContentInsetStartWithNavigation這個值
mContentInsetStartWithNavigation這個值就是從contentInsetStartWithNavigation這個屬性中取得的
getContentInsetStart()這個返回的值就是contentInsetStart這個屬性對應的值

所以最后就是比較contentInsetStart和contentInsetStartWithNavigation這兩個屬性的值


OK,接下來我們來看這兩個屬性的值在V22.2.0和V24.0.0的版本中到底是多少
具體的文件為首先找到對應版本的appcompact-v7包的aar文件
然后解壓找到/res/values/values.xml這個文件

首先說明默認Toolbar的Style是Widget.AppCompat.Toolbar
Widget.AppCompat.Toolbar的Parent是Base.Widget.AppCompat.Toolbar
所以只要找到Base.Widget.AppCompat.Toolbar對應的Style就OK了
首先我們來看V22.2.0版本中葬荷,我找到了描述Toolbar屬性的這段內(nèi)容

<style name="Base.Widget.AppCompat.Toolbar" parent="android:Widget">
    <item name="titleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Title</item>
    <item name="subtitleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Subtitle</item>
    <item name="android:minHeight">?attr/actionBarSize</item>
    <item name="titleMargins">4dp</item>
    <item name="maxButtonHeight">56dp</item>
    <item name="collapseIcon">?attr/homeAsUpIndicator</item>
    <item name="collapseContentDescription">@string/abc_toolbar_collapse_description</item>
    <item name="contentInsetStart">16dp</item>
</style>

我們發(fā)現(xiàn)contentInsetStart這個是16dp涨共,而沒有contentInsetStartWithNavigation這個屬性,這是因為contentInsetStartWithNavigation這個屬性是在V22之后的版本才加上的宠漩,而V22的Toolbar代碼中只會根據(jù)contentInsetStart來計算Title的左邊距
接下來我們來看V24.0.0版本中的代碼

<style name="Base.Widget.AppCompat.Toolbar" parent="android:Widget">
    <item name="titleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Title</item>
    <item name="subtitleTextAppearance">@style/TextAppearance.Widget.AppCompat.Toolbar.Subtitle</item>
    <item name="android:minHeight">?attr/actionBarSize</item>
    <item name="titleMargin">4dp</item>
    <item name="maxButtonHeight">@dimen/abc_action_bar_default_height_material</item>
    <item name="buttonGravity">top</item>
    <item name="collapseIcon">?attr/homeAsUpIndicator</item>
    <item name="collapseContentDescription">@string/abc_toolbar_collapse_description</item>
    <item name="contentInsetStart">16dp</item>
    <item name="contentInsetStartWithNavigation">@dimen/abc_action_bar_content_inset_with_nav</item>
    <item name="android:paddingLeft">@dimen/abc_action_bar_default_padding_start_material</item>
    <item name="android:paddingRight">@dimen/abc_action_bar_default_padding_end_material</item>
</style>

OK,contentInsetStart這個也是16dp举反,contentInsetStartWithNavigation這個定義在dimen中,我們來看看這個值

<dimen name="abc_action_bar_content_inset_with_nav">72dp</dimen>

OK,我們回過來看這段代碼

//核心的方法扒吁,返回就是那個讓距離錯誤的值
final int contentInsetLeft = getCurrentContentInsetLeft();
//left會從之前的left值也就是計算過Navigation的距離之后 和contentInsetLeft比較火鼻,取最大值
left = Math.max(left, contentInsetLeft);

left的值一開始是NavigationIcon的寬度,一般為56dp雕崩,而contentInsetLeft這個值是72dp,所以left的值就變成了72dp魁索,就最后導致了距離顯示異常

至此,我們終于了解了這個錯誤的來龍去脈盼铁,不僅了解了怎么改粗蔚,也了解了為什么這么改,同時了解了Toolbar的相關代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饶火,一起剝皮案震驚了整個濱河市鹏控,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌趁窃,老刑警劉巖牧挣,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異醒陆,居然都是意外死亡瀑构,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門刨摩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寺晌,“玉大人,你說我怎么就攤上這事澡刹∩胝鳎” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵罢浇,是天一觀的道長陆赋。 經(jīng)常有香客問我,道長嚷闭,這世上最難降的妖魔是什么攒岛? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮胞锰,結(jié)果婚禮上灾锯,老公的妹妹穿的比我還像新娘。我一直安慰自己嗅榕,他們只是感情好顺饮,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布吵聪。 她就那樣靜靜地躺著,像睡著了一般兼雄。 火紅的嫁衣襯著肌膚如雪吟逝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天君旦,我揣著相機與錄音澎办,去河邊找鬼嘲碱。 笑死金砍,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的麦锯。 我是一名探鬼主播恕稠,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扶欣!你這毒婦竟也來了鹅巍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤料祠,失蹤者是張志新(化名)和其女友劉穎骆捧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體髓绽,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡敛苇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了顺呕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枫攀。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡狐榔,死狀恐怖褒搔,靈堂內(nèi)的尸體忽然破棺而出好爬,到底是詐尸還是另有隱情腋逆,我是刑警寧澤咐蚯,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布把兔,位于F島的核電站丐怯,受9級特大地震影響户辞,放射性物質(zhì)發(fā)生泄漏僵闯。R本人自食惡果不足惜卧抗,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望棍厂。 院中可真熱鬧颗味,春花似錦、人聲如沸牺弹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晶默,卻和暖如春谨娜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背磺陡。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工趴梢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人币他。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓坞靶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蝴悉。 傳聞我的和親對象是個殘疾皇子彰阴,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,522評論 25 707
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,358評論 0 17
  • 本文出自 “阿敏其人” 簡書博客,轉(zhuǎn)載或引用請注明出處庆杜。 一射众、Google口中的ToolBar 從Toolbar說...
    阿敏其人閱讀 4,188評論 2 36
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)晃财,斷路器叨橱,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • 黑暗中的四肢像是被空氣中的懸浮顆粒托起來,變得越來越輕盈拓劝,化蝶了么雏逾?一顆堅強的心被嗔念癡念欲念層層包裹得嚴嚴實實,...
    禾葉兄弟閱讀 241評論 0 1