fitsSystemWindows理解

fitsSystemWindows 的定義

Boolean internal attribute to adjust view layout based on system windows such as the status bar. If true, adjusts the padding of this view to leave space for the system windows. Will only take effect if this view is in a non-embedded activity.

這個一個boolean值的內(nèi)部屬性糖声,讓view可以根據(jù)系統(tǒng)窗口(如status bar)來調(diào)整自己的布局朱巨,如果值為true,就會調(diào)整view的paingding屬性來給system windows留出空間。只有在非嵌入式的activity的view才有效果秕噪。

fitsSystemWindows 的作用

android:fitsSystemWindows="true" attribute gives you: it sets the padding of the View to ensure the contents don’t overlay the system windows.

設置View的padding畴博,確定content不會與system windows重疊临燃。

A few things to keep in mind:

  • fitsSystemWindows is applied depth first *?—?ordering matters: it’s the first View that consumes the insets that makes a difference
    Insets are always relative to the full window?—?insets may be applied even before layout happens, so don’t assume the default behavior knows anything about the position of a View when applying its padding
    Any other padding you’ve set is overwritten?—?you’ll note that paddingLeft /paddingTop /etc is ineffective if you are using android:fitsSystemWindows="true" on the same View

有幾點是需要注意的:

  • 屬性需要在root view設置鳄虱,只有root view消費insets才會生效诗力。
  • insets 是相對于全屏幕的凰浮。insets(邊框)可能在 layout 之前(view生產(chǎn)之前)就已經(jīng)設置, 所以insets的padding值苇本,絕不會是相對于view的位置袜茧,而是相對于全屏幕。
  • 任何你設置的padding都會被覆蓋瓣窄。 在同一個view上面設置了 android:fitsSystemWindows="true" 的同時笛厦,還設置了 paddingLeft paddingTop 等等,后者不會生效俺夕。

如果想讓RecycleView的內(nèi)容滾動到狀態(tài)欄之下, 可以同時設置android:fitsSystemWindows="true"和android:clipToPadding="false", 這樣在布局初始化的時候,內(nèi)容不會在狀態(tài)欄之下, 滾動的時候, 內(nèi)容可以滾到狀態(tài)欄之下;
::android:clipToPadding="false"的作用是是讓padding的位置也可以用來繪制, clipToPadding默認是true::

自定義fitsSystemWindows

On KitKat and below, your custom View could override fitSystemWindows()
and provide any functionality you wanted?—?just return true
if you’ve consumed the insets or false if you’d like to give other Views a chance.

在KitKat(4.4)或者4.4以下的版本裳凸,在自定義view中重寫fitSystemWindows()方法贱鄙,如果要消費insets則返回true , 返回false則讓其他view去消費。

on Lollipop and higher devices, we provide some new APIs to make customizing this behavior much easier and consistent with other behaviors for Views. You’ll instead override onApplyWindowInsets(), which allows the View to consume as much or as little of the insets as you need and be able to call dispatchApplyWindowInsets() on child views as needed.

Lollipop(5.0) 或者 5.0以上版本姨谷, 提供了新的API ,只要重寫onApplyWindowInsets()逗宁,就能允許自定義view去消費任何大小的insets ,并且能調(diào)用dispatchApplyWindowInsets() 讓子view接著消費insets梦湘。

you don’t even need to subclass your Views if you only need custom behavior on Lollipop and higher??you can use ViewCompat.setOnApplyWindowInsetsListener(), which will be given preference over the View’s onApplyWindowInsets(). ViewCompat also provides helper methods for calling onApplyWindowInsets() and dispatchApplyWindowInsets() without version checking.

在Lollipop(5.0)或者5.0以上的版本瞎颗,如果不想繼承view的話,可以使用ViewCompat.setOnApplyWindowInsetsListener() , 這個方法優(yōu)先于View.onApplyWindowInsets()執(zhí)行捌议。
ViewCompat 同時也提供了 onApplyWindowInsets() dispatchApplyWindowInsets() ,解決了兼容性的問題言缤。

fitsSystemWindows 源碼

根據(jù)FITS_SYSTEM_WINDOWS標志位,無論哪個版本禁灼,默認都是直接設置padding

protected boolean fitSystemWindows(Rect insets) {
        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
            if (insets == null) {
                // Null insets by definition have already been consumed.
                // This call cannot apply insets since there are none to apply,
                // so return false.
                return false;
            }
            // If we're not in the process of dispatching the newer apply insets call,
            // that means we're not in the compatibility path. Dispatch into the newer
            // apply insets path and take things from there.
            try {
                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
            } finally {
                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
            }
        } else {
            // We're being called from the newer apply insets path.
            // Perform the standard fallback behavior.
            return fitSystemWindowsInt(insets);
        }
    }

    private boolean fitSystemWindowsInt(Rect insets) {
        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
            mUserPaddingStart = UNDEFINED_PADDING;
            mUserPaddingEnd = UNDEFINED_PADDING;
            Rect localInsets = sThreadLocal.get();
            if (localInsets == null) {
                localInsets = new Rect();
                sThreadLocal.set(localInsets);
            }
            boolean res = computeFitSystemWindows(insets, localInsets);
            mUserPaddingLeftInitial = localInsets.left;
            mUserPaddingRightInitial = localInsets.right;
            internalSetPadding(localInsets.left, localInsets.top,
                    localInsets.right, localInsets.bottom);
            return res;
        }
        return false;
    }
  public WindowInsets onApplyWindowInsets(WindowInsets insets) {
        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
            // We weren't called from within a direct call to fitSystemWindows,
            // call into it as a fallback in case we're in a class that overrides it
            // and has logic to perform.
            if (fitSystemWindows(insets.getSystemWindowInsets())) {
                return insets.consumeSystemWindowInsets();
            }
        } else {
            // We were called from within a direct call to fitSystemWindows.
            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
                return insets.consumeSystemWindowInsets();
            }
        }
        return insets;
    }

fitsSystemWindows實例

系統(tǒng)的基本控件((FrameLayout, LinearLayout, 等)都使用默認的行為管挟,Support 包中有些控件使用了自定義行為。
一個使用自定義行為的示例就是側邊欄弄捕,側邊欄打開的時候僻孝,內(nèi)容是占滿整個屏幕高度的,狀態(tài)欄顯示為透明的守谓,下面是 側邊欄的內(nèi)容穿铆。


這里 DrawerLayout 使用 fitsSystemWindows 來表明需要處理 insets,但是仍然使用狀態(tài)欄的顏色來繪制狀態(tài)欄背景(狀態(tài)欄顏色為 主題的 colorPrimaryDark 所設置的顏色)斋荞。
然后 DrawerLayout 在每個子 View 上調(diào)用 dispatchApplyWindowInsets() 函數(shù)荞雏,這樣 子 View 也有 機會處理 insets,這和系統(tǒng)默認行為是不一樣的(系統(tǒng)默認行為只是吃掉這個 insets平酿,然后子 View 無法繼續(xù)處理)凤优。
CoordinatorLayout 對此也做了特殊處理,讓每個子 View 的 Behavior 可以根據(jù)系統(tǒng)窗口的大小來做不同的處理蜈彼。 還使用 fitsSystemWindows 屬性來判斷是否需要繪制狀態(tài)欄背景筑辨。
通用 CollapsingToolbarLayout 也根據(jù) fitsSystemWindows 屬性來確定何時何地繪制 內(nèi)容上方的半透明背景。
cheesesquare 示例項目中演示了這些 fitsSystemWindows 使用場景幸逆,可以下載該示例項目查看如何使用的棍辕。

也可以參考這個項目:

https://github.com/Jude95/FitSystemWindowLayout

參考:
https://stackoverflow.com/questions/3355367/height-of-statusbar
http://blog.chengyunfeng.com/?p=905
https://stackoverflow.com/questions/28387289/fitsystemwindows-programmatically-for-status-bar-transparency
http://www.reibang.com/p/f3683e27fd94
https://developer.android.com/reference/android/support/design/widget/AppBarLayout.html
https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec?linkId=19685562
https://github.com/hehonghui/android-tech-frontier/blob/master/issue-35/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E4%BB%AC%E8%A6%81%E7%94%A8fitsSystemWindows.md

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市还绘,隨后出現(xiàn)的幾起案子楚昭,更是在濱河造成了極大的恐慌,老刑警劉巖拍顷,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抚太,死亡現(xiàn)場離奇詭異,居然都是意外死亡菇怀,警方通過查閱死者的電腦和手機凭舶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門晌块,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人帅霜,你說我怎么就攤上這事匆背。” “怎么了身冀?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵钝尸,是天一觀的道長。 經(jīng)常有香客問我搂根,道長珍促,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任剩愧,我火速辦了婚禮猪叙,結果婚禮上,老公的妹妹穿的比我還像新娘仁卷。我一直安慰自己穴翩,他們只是感情好,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布锦积。 她就那樣靜靜地躺著芒帕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丰介。 梳的紋絲不亂的頭發(fā)上背蟆,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天,我揣著相機與錄音哮幢,去河邊找鬼带膀。 笑死,一個胖子當著我的面吹牛家浇,可吹牛的內(nèi)容都是我干的本砰。 我是一名探鬼主播碴裙,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钢悲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了舔株?” 一聲冷哼從身側響起莺琳,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎载慈,沒想到半個月后惭等,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡办铡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年辞做,在試婚紗的時候發(fā)現(xiàn)自己被綠了琳要。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡秤茅,死狀恐怖稚补,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情框喳,我是刑警寧澤课幕,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站五垮,受9級特大地震影響乍惊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜放仗,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一润绎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诞挨,春花似錦凡橱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至达罗,卻和暖如春坝撑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粮揉。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工巡李, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人扶认。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓侨拦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辐宾。 傳聞我的和親對象是個殘疾皇子狱从,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評論 25 707
  • afinalAfinal是一個android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,429評論 2 45
  • 需要引用到的頭文件有 相冊權限 照相機權限 麥克風權限 通知權限 定位權限 通訊錄權限
    SincereDu閱讀 427評論 0 0
  • 早上一起床叠纹,兒子就出去了季研。直到午飯時間給他打電話,接近12點才回來誉察。吃飯時与涡,兒子:媽媽,我給你說過幾次我要上班的事...
    小瓶蓋Q日記閱讀 339評論 1 1
  • 在2017.5.14macaca發(fā)布了 XCTestWD 、UIAutomatorWD驼卖,接下來就是面臨各種的升級問...
    _夏兮閱讀 1,052評論 0 2