Material Design 開(kāi)發(fā)筆記 (持續(xù)更新...)

1. FitSystemWindow

在 layout 布局中設(shè)置 android:fitsSystemWindows="true" 到底發(fā)生了什么?
默認(rèn)的 View的行為是在該屬性設(shè)置后,系統(tǒng)通過(guò)在布局中預(yù)留出padding,使得布局有個(gè)相對(duì)的偏移。特別的, 在頂層layout是 CoordinatorLayoutDrawerLayout,或是CollapsingToolbarLayout時(shí),這些layout (相比一般的布局,如FrameLayout) 已經(jīng)有了自定義的行為。

1.1 以 CoordinatorLayout 為例

if (ViewCompat.getFitsSystemWindows(this)) {
    if (mApplyWindowInsetsListener == null) {
        mApplyWindowInsetsListener =
            new androidx.core.view.OnApplyWindowInsetsListener() {
                @Override
                public WindowInsetsCompat onApplyWindowInsets(View v,
                        WindowInsetsCompat insets) {
                    return setWindowInsets(insets);
                }
            };
    }
    // First apply the insets listener
    ViewCompat.setOnApplyWindowInsetsListener(this, mApplyWindowInsetsListener);

    // Now set the sys ui flags to enable us to lay out in the window insets
    setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

在5.0+系統(tǒng)中, 其方法setupForInsets()會(huì)檢測(cè) fitsSystemWindows屬性是否有設(shè)置過(guò),如果有,則設(shè)置當(dāng)前View的屬性為View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 然后進(jìn)一步調(diào)用dispatchApplyWindowInsetsToBehaviors,將WindowInsetsCompat 傳遞個(gè)也設(shè)置過(guò)fitsSystemWindows子view的Behavior class,直至WindowInsetsCompat被最終消費(fèi)掉(consumed)。

private WindowInsetsCompat dispatchApplyWindowInsetsToBehaviors(WindowInsetsCompat insets) {
    if (insets.isConsumed()) {
        return insets;
    }

    for (int i = 0, z = getChildCount(); i < z; i++) {
        final View child = getChildAt(i);
        if (ViewCompat.getFitsSystemWindows(child)) {
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            final Behavior b = lp.getBehavior();

            if (b != null) {
                // If the view has a behavior, let it try first
                insets = b.onApplyWindowInsets(this, child, insets);
                if (insets.isConsumed()) {
                    // If it consumed the insets, break
                    break;
                }
            }
        }
    }

    return insets;
}   

1.2 Inset issue (e.g. Fragment transition)

在單Activity 多Fragment的UI結(jié)構(gòu)下,可能出現(xiàn)多個(gè)Fragment的布局都需要處理 Window insets的情況。而實(shí)際上ViewGroup#dispatchApplyWindowInsets()默認(rèn)的實(shí)現(xiàn)中是會(huì)遍歷子View (DFS),開(kāi)始dispatch window insets 直至有子view消費(fèi)了insets。這就意味著,一旦有子view消費(fèi)了insets,后續(xù)的子view就不會(huì)再有機(jī)會(huì)處理insets。

所以對(duì)應(yīng)的解決方法就是在Fragment的 Container中借助OnApplyWindowInsetsListener 改寫(xiě)處理insets的機(jī)制。

fragment_container.setOnApplyWindowInsetsListener { view, insets ->
  var consumed = false

  (view as ViewGroup).forEach { child ->
    // Dispatch the insets to the child
    val childResult = child.dispatchApplyWindowInsets(insets)
    // If the child consumed the insets, record it
    if (childResult.isConsumed) {
      consumed = true
    }
  }

  // If any of the children consumed the insets, return
  // an appropriate value
  if (consumed) insets.consumeSystemWindowInsets() else insets
}

1.3 代碼實(shí)踐

  • 如果你使用了 CoordinatorLayout 或是 DrawerLayout,而且想要在system bars (包括status bar) 之下顯示 View,可在其直接的子View中(遞歸地)指定android:fitsSystemWindows="true"

  • 對(duì)于當(dāng)前status Bar顏色的設(shè)置,一般地為了能讓自定義的view填充status bar的background區(qū)域,statusBarColor通常設(shè)置為transparent :
    Window#setStatusBarColor(int)
    或在Activity Theme中指定為:
    <item name="android:statusBarColor">@android:color/transparent</item>

  • 如果想要獲取status bar的高度,不必使用hardcoded value (24 dp) 或是讀取系統(tǒng)resource,可通過(guò)監(jiān)聽(tīng)系統(tǒng) WindowInsets 實(shí)現(xiàn):

myView.setOnApplyWindowInsetsListener { view, insets ->
    val statusBarSize = insets.systemWindowInsetTop
    return insets
}

2. Fragment中添加 Option Menu

一般來(lái)說(shuō),常見(jiàn)的對(duì)于ActionBar的處理是放在Host Activity中。但根據(jù)特定的的UI設(shè)計(jì),F(xiàn)ragment中可能都有自定義的ActionBar,故將ActionBar的建立以及menu的響應(yīng)處理分散到各自的Fragment中,這是更為內(nèi)聚的做法。

常見(jiàn)的在Fragment中使用Options Menu 需要注意:

2.1 啟用menu

在Fragment中設(shè)置setHasOptionsMenu(true)。

2.2 ActionBar 的對(duì)應(yīng)更新

由于其它Fragment中也有設(shè)置 menu,在切換Fragment后,當(dāng)前Activity關(guān)聯(lián)的的ActionBar可能已經(jīng)不是對(duì)應(yīng)到當(dāng)前的Fragment了,此時(shí)需要重新設(shè)置當(dāng)前的ActionBar :

// toolbar in current Fragment
setSupportActionBar(toolbar)

4. References

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評(píng)論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,980評(píng)論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 64,064評(píng)論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評(píng)論 6 414
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,109評(píng)論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,287評(píng)論 0 291
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評(píng)論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評(píng)論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,327評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,667評(píng)論 1 296
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評(píng)論 2 380