在繪制View時(shí),首先由根布局往下傳WindowInsets,SystemBar的尺寸在WindowInsets 中表示出來,比如Insets:(0, 63 , 0, 126), 表示StatusBar高度63,NavigationBar高度126。
根據(jù)默認(rèn)的實(shí)現(xiàn),如果設(shè)置了fitSystemWindows = true,就會(huì)根據(jù)WindowInsets來設(shè)置padding,調(diào)用insets.consumeSystemWindowInsets()表示這個(gè)WindowInsets被消耗了,之后就不會(huì)往下傳。所以如果在布局文件了有多個(gè)View設(shè)置了fitSystemWindows = true,那只有第一個(gè)起作用。
要自己根據(jù)WindowInsets來做處理,可復(fù)寫onApplyWindowInsets方法,也可以注冊(cè)監(jiān)聽setOnApplyWindowInsetsListener。
一個(gè)實(shí)現(xiàn)FitSystemWindows的自定義View:
package com.devbrackets.android.exomedia.ui.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Build;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.WindowInsets;
import android.widget.RelativeLayout;
/**
* A RelativeLayout that will abide by the fitsSystemWindows flag without
* consuming the event since Android has been designed to only allow
* one view with fitsSystemWindows=true at a time.
*/
public class FitsSystemWindowRelativeLayout extends RelativeLayout {
private Rect originalPadding;
public FitsSystemWindowRelativeLayout(Context context) {
super(context);
setup();
}
public FitsSystemWindowRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public FitsSystemWindowRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setup();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public FitsSystemWindowRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setup();
}
/**
* Makes sure the padding is correct for the orientation
*/
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//If the system navigation bar can move, then clear out the previous insets before
// fitSystemWindows(...) or onApplyWindowInsets(...) is called
//This fixes the issue https://github.com/brianwernick/ExoMedia/issues/33
if (navBarCanMove()) {
setup();
}
}
@Override
@SuppressWarnings("deprecation")
protected boolean fitSystemWindows(@NonNull Rect insets) {
updatePadding(insets);
return false;
}
@Override
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Rect windowInsets = new Rect(
insets.getSystemWindowInsetLeft(),
insets.getSystemWindowInsetTop(),
insets.getSystemWindowInsetRight(),
insets.getSystemWindowInsetBottom()
);
fitSystemWindows(windowInsets);
return insets;
}
/**
* Updates the views padding so that any children views are correctly shown next to, and
* below the system bars (NavigationBar and Status/SystemBar) instead of behind them.
*/
private void setup() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
setFitsSystemWindows(true);
}
if (originalPadding == null) {
originalPadding = new Rect(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom());
}
updatePadding(new Rect());
}
/**
* Updates the layouts padding by using the original padding and adding
* the values found in the insets.
*
* @param insets The Rect containing the additional insets to use for padding
*/
private void updatePadding(Rect insets) {
int rightPadding = originalPadding.right + insets.right;
int bottomPadding = originalPadding.bottom + insets.bottom;
int topPadding = originalPadding.top + insets.top;
setPadding(originalPadding.left, topPadding, rightPadding, bottomPadding);
}
/**
* Determines if the Navigation controller bar can move. This will typically only be
* true for phones.
*
* @return True if the system navigation buttons can move sides
*/
private boolean navBarCanMove() {
return this.getResources().getConfiguration().smallestScreenWidthDp <= 600;
}
}
這個(gè)自定義View在onApplyWindowInsets中根據(jù)上面?zhèn)飨聛淼腤indowInsets做了相應(yīng)的處理,但是并沒有調(diào)用insets.consumeSystemWindowInsets(),所以WindowInsets還是會(huì)繼續(xù)往下傳,這樣可以解決同一個(gè)布局里面只有第一個(gè)fitSystemWindows = true才起作用的問題。