您好,登錄后才能下訂單哦!
今天小編給大家分享一下Android SystemBar如何使用的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
ROM 去掉NavigationBar
resgrep NavigationBar相關的res,發現在framework/base/core/res/res/config.xml中可以通過config_showNavigationBar配置,繼續jgrep showNavigationBar相關的java,發現在PhoneWindowManager中通過boolean變量mHasNavigationBar記錄是否有NavigationBar,具體代碼如下:
mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
需要注意的是mHasNavigationBar也可以通過系統提供的Property來標識,具體代碼如下:
String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
if ("1".equals(navBarOverride)) {
mHasNavigationBar = false;
} else if ("0".equals(navBarOverride)) {
mHasNavigationBar = true;
}
在PhoneWindowManager中存在一個類型為WindowState的變量mNavigationBar,WindowState是在PhoneWindowManger prepareAddWindow時會用到的一個interface,仔細看看prepareAddWindowLw方法
switch (attrs.type) {
case TYPE_NAVIGATION_BAR:
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE, "PhoneWindowManager");
if (mNavigationBar != null) {
if (mNavigationBar.isAlive()) {
return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
}
mNavigationBar = win;
mNavigationBarController.setWindow(win);
if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break;
}
判斷type為TYPE_NAVIGATION_BAR的時候,給mNavigationBar賦值,并且mNavigationBarController setWindow,mNavigationBarController是一個用來操縱SystemBar Window的類,有興趣可以詳細看看這個類,位于/framework/base/services/core/java/com/android/server/policy。繼續瀏覽代碼會發現方法layoutNavigationBar,通過mNavigationBarController對mNavigationBar進行layout。
在framework/base/packages/SystemUI中PhoneStatusBar中makeStatusBarView有如下一段代碼:
try {
boolean showNav = mWindowManagerService.hasNavigationBar();
if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
if (showNav) {
createNavigationBarView(context);
}
} catch (RemoteException ex) {
// no window manager? good luck with that
}
根據WindowManagerService中的hasNavigationBar方法判斷是否有NavigationBar,再看WindowMangerService中是調用了PhoneWindowManager中的hasNavigationBar方法,最終返回的就是最開始提到了mHasNavigationBar這個標識。在PhoneStatusBar有詳細講到如何createAndAddWindows,感興趣可以再進一步了解。
SystemBar Translucent支持
Android在API 19的時候添加了兩個WindowManager.LayoutParams,分別是FLAG_TRANSLUCENT_NAVIGATION、FLAG_TRANSLUCENT_STATUS。
在官方文檔中有提到當為Window設置FLAG_TRANSLUCENT_NAVIGATION時,自動設置了System UI visibility SYSTEM_UI_FLAG_LAYOUT_STABLE、SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,當為Window設置了FLAG_TRANSLUCENT_STATUS時,自動設置了System UI visibility SYSTEM_UI_FLAG_LAYOUT_STABLE、SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN。
顯然,這時System UI visibility有發生變化,在PhoneWindowManager中有如下一段代碼:
public int adjustSystemUiVisibilityLw(int visibility) {
mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0;
mTvPictureInPictureVisible = (visibility & View.TV_PICTURE_IN_PICTURE_VISIBLE) > 0;
// Reset any bits in mForceClearingStatusBarVisibility that
// are now clear.
mResettingSystemUiFlags &= visibility;
// Clear any bits in the new visibility that are currently being
// force cleared, before reporting it.
return visibility & ——mResettingSystemUiFlags
& ——mForceClearedSystemUiFlags;
}
可以看到前邊提到的操控SystemBar的Controller這個時候發揮了作用,調用了其adjustSystemUiVisibilityLw,繼續看BarController中相關代碼
public void adjustSystemUiVisibilityLw(int oldVis, int vis) {
if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING && (vis & mTransientFlag) == 0) {
// sysui requests hide
setTransientBarState(TRANSIENT_BAR_HIDING);
setBarShowingLw(false);
} else if (mWin != null && (oldVis & mUnhideFlag) != 0 && (vis & mUnhideFla == 0) {
// sysui ready to unhide
setBarShowingLw(true);
}
}
同時,看到BarController中有applyTranslucentFlagLw,通過查找其調用處,發現依舊是在PhoneWindowManager中調用,以下是調用部分
// apply translucent bar vis flags
WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen ? mStatusBar : mTopFullscreenOpaqueWindowState;
vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVs);
vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
final int dockedVis = mStatusBarController.applyTranslucentFlagLw(mTopDockedOpaqueWindowState, 0, 0);
final boolean fullscreenDrawsStatusBarBackground =
(drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
final boolean dockedDrawsStatusBarBackground = (drawsSystemBarBackground(mTopDockedOpaqueWindowState) && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
可以看到在PhoneWindowManager中通過updateSystemBarsLw進行了相應的更新SystemBars。這個地方還有一個比較有意思的問題是,在實際使用這兩個Flag的時候,會發現App自動延伸到StatusBar和NavigationBar下方,這是為何?
猜想,應該是App區域對系統下發的WindowInsets值做了處理,查看ActionBarOverlayLayout onApplyWindowInsets方法,可以發現通過computeFitSystemWindows對ActionBarOverlayLayout的measure時用到的insets值做了處理,查看View的computeFitSystemWindows方法
protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 || mAttachInfo == null || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0 && !mAttachInfo.mOverscanRequested)) {
outLocalInsets.set(inoutInsets);
inoutInsets.set(0, 0, 0, 0);
return true;
} else {
// The application wants to take care of fitting system window for
// the content... however we still need to take care of any overscan here.
final Rect overscan = mAttachInfo.mOverscanInsets;
outLocalInsets.set(overscan);
inoutInsets.left -= overscan.left;
inoutInsets.top -= overscan.top;
inoutInsets.right -= overscan.right;
inoutInsets.bottom -= overscan.bottom;
return false;
}
}
可以發現這個地方,根據flag的判斷通過overscan Rect對ActionBarOverlayLayout的insets值進行了修改(最近把這個處理移植到API 19以下了,嘿嘿嘿)。當然Google也沒勇氣對這個處理一鍋端,因此App可以使用fitsSystemWindows屬性來避免系統做這個處理,通過這個屬性可以默認把insets值給到當前View的padding值,當然App也可以自己繼承View的fitSystemWindows方法來自己處理insets。
SystemBar setColor支持
Android在API 21的時候為Window添加了setNavigationBarColor、setStatusBarColor,進一步提升SystemBar用戶體驗。
PhoneWindow繼承Window具體實現了setNavigationBarColor、setStatusBarColor,具體代碼如下:
public void setStatusBarColor(int color) {
mStatusBarColor = color;
mForcedStatusBarColor = true;
if (mDecor != null) {
mDecor.updateColorViews(null, false /* animate */);
}
}
public void setNavigationBarColor(int color) {
mNavigationBarColor = color;
mForcedNavigationBarColor = true;
if (mDecor != null) {
mDecor.updateColorViews(null, false /* animate */);
mDecor.updateNavigationGuardColor();
}
}
不難發現主要是DecorView的updateColorViews在work,通過查看代碼,可以明白是DecorView在SystemBar的位置add了對應的ColorStateView,這個有點類似PhoneWindowManager里邊的WindowState,之后對ColotStateView里邊的view進行操作即可,比如說setBackground來改變其顏色。
以上就是“Android SystemBar如何使用”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。