今天我们打卡学习的内容是Android 10.0 修改导航栏横屏固定在底部显示,首先声明此次打卡学习的链接文章链接将会放置文章最后处,有需要的小伙伴可以自行去查阅观看。
在Android 10.0的产品时,我们会遇到一些横屏的产品中导航栏不是在顶部,而是出现在右侧,这样既不美观也不方便,此时我们需要将其调制底部显示,这样看起来才更加美观方便。
处理方法
DisplayPolicy.java
附:
Android Display:Android 显示设置的 AOSP 实现,包括应用快捷方式、圆形启动器图标、请勿打扰 (DND)、多窗口(分屏、自由格式和画中画)、高动态范围 (HDR) 视频、夜间模式和零售演示模式。
Android Display 系统分析
其大致分为以下这些:
Android Display 框架
Android SurfaceFlinger中Display部分
Android Framework 中Display 部分
DisplayManagerService对display的管理
WindowManagerService对Display的管理
Android系统转屏问题
相关知识参考这篇文章:Android Display 系统分析 - 算法网 (itpcb.com)
android如何设置横屏和竖屏
如果不想让软件在横竖屏之间切换,最简单的办法就是在项目的AndroidManifest.xml中找到你所指定的activity加上android:screenOrientation属性
参数如下:
"landscape": 横屏显示
"portrait": 竖屏显示
"user": 用户当前首选的方向
"behind": 和该Activity下面的那个Activity的方向一致。
"unspecified": 默认值是由系统来判断显示方向。判定的策略是和设备相关的,不同的设备会有不同的显示方向.
"sensor": 有物理的感应器来决定。这样根据用户旋转也会实现相应变化
"nosensor": 忽略物理感应器。这样根据用户旋转不会实现相应变化。
或者在java代码中设置
在java代码中可以分别通过:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)以及setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)代码实现横屏竖屏的变化。
相关主要代码
DisplayPolicy(WindowManagerService service, DisplayContent displayContent) { mService = service; mContext = displayContent.isDefaultDisplay ? service.mContext : service.mContext.createDisplayContext(displayContent.getDisplay()); mDisplayContent = displayContent; mLock = service.getWindowManagerLock(); final int displayId = displayContent.getDisplayId(); mStatusBarController = new StatusBarController(displayId); mNavigationBarController = new BarController("NavigationBar", displayId, View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_UNHIDE, View.NAVIGATION_BAR_TRANSLUCENT, StatusBarManager.WINDOW_NAVIGATION_BAR, FLAG_TRANSLUCENT_NAVIGATION, View.NAVIGATION_BAR_TRANSPARENT); final Resources r = mContext.getResources(); mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer); mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer); mForceShowSystemBarsFromExternal = r.getBoolean(R.bool.config_forceShowSystemBars); mAccessibilityManager = (AccessibilityManager) mContext.getSystemService( Context.ACCESSIBILITY_SERVICE); if (!displayContent.isDefaultDisplay) { mAwake = true; mScreenOnEarly = true; mScreenOnFully = true; } final Looper looper = UiThread.getHandler().getLooper(); mHandler = new PolicyHandler(looper); mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler, new SystemGesturesPointerEventListener.Callbacks() { @Override public void onSwipeFromTop() { if (mStatusBar != null) { requestTransientBars(mStatusBar); } } @Override public void onSwipeFromBottom() { if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) { requestTransientBars(mNavigationBar); } } @Override public void onSwipeFromRight() { final Region excludedRegion; synchronized (mLock) { excludedRegion = mDisplayContent.calculateSystemGestureExclusion(); } final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture || mNavigationBarPosition == NAV_BAR_RIGHT; if (mNavigationBar != null && sideAllowed && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) { requestTransientBars(mNavigationBar); } } @Override public void onSwipeFromLeft() { final Region excludedRegion; synchronized (mLock) { excludedRegion = mDisplayContent.calculateSystemGestureExclusion(); } final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture || mNavigationBarPosition == NAV_BAR_LEFT; if (mNavigationBar != null && sideAllowed && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) { requestTransientBars(mNavigationBar); } } @Override public void onFling(int duration) { if (mService.mPowerManagerInternal != null) { mService.mPowerManagerInternal.powerHint( PowerHint.INTERACTION, duration); } } @Override public void onDebug() { // no-op } private WindowOrientationListener getOrientationListener() { final DisplayRotation rotation = mDisplayContent.getDisplayRotation(); return rotation != null ? rotation.getOrientationListener() : null; } @Override public void onDown() { final WindowOrientationListener listener = getOrientationListener(); if (listener != null) { listener.onTouchStart(); } } @Override public void onUpOrCancel() { final WindowOrientationListener listener = getOrientationListener(); if (listener != null) { listener.onTouchEnd(); } } @Override public void onMouseHoverAtTop() { mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS; mHandler.sendMessageDelayed(msg, 500 /* delayMillis */); } @Override public void onMouseHoverAtBottom() { mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION; mHandler.sendMessageDelayed(msg, 500 /* delayMillis */); } @Override public void onMouseLeaveFromEdge() { mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); } }); displayContent.registerPointerEventListener(mSystemGestures); displayContent.mAppTransition.registerListenerLocked( mStatusBarController.getAppTransitionListener()); mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper, mService.mVrModeEnabled); mAcquireSleepTokenRunnable = () -> { if (mWindowSleepToken != null) { return; } mWindowSleepToken = service.mAtmInternal.acquireSleepToken( "WindowSleepTokenOnDisplay" + displayId, displayId); }; mReleaseSleepTokenRunnable = () -> { if (mWindowSleepToken == null) { return; } mWindowSleepToken.release(); mWindowSleepToken = null; }; // TODO: Make it can take screenshot on external display mScreenshotHelper = displayContent.isDefaultDisplay ? new ScreenshotHelper(mContext) : null; if (mDisplayContent.isDefaultDisplay) { mHasStatusBar = true; mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar); // Allow a system property to override this. Used by the emulator. // See also hasNavigationBar(). String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); if ("1".equals(navBarOverride)) { mHasNavigationBar = false; } else if ("0".equals(navBarOverride)) { mHasNavigationBar = true; } } else { mHasStatusBar = false; mHasNavigationBar = mDisplayContent.supportsSystemDecorations(); } mRefreshRatePolicy = new RefreshRatePolicy(mService, mDisplayContent.getDisplayInfo(), mService.mHighRefreshRateBlacklist); } void systemReady() { mSystemGestures.systemReady(); if (mService.mPointerLocationEnabled) { setPointerLocationEnabled(true); } } private int getDisplayId() { return mDisplayContent.getDisplayId(); } public boolean hasNavigationBar() { return mHasNavigationBar; } public boolean hasStatusBar() { return mHasStatusBar; } public boolean navigationBarCanMove() { return mNavigationBarCanMove; } @NavigationBarPosition int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { if (navigationBarCanMove() && displayWidth > displayHeight) { if (displayRotation == Surface.ROTATION_270) { return NAV_BAR_LEFT; } else if (displayRotation == Surface.ROTATION_90) { return NAV_BAR_RIGHT; } } return NAV_BAR_BOTTOM; } boolean canNavigationBarMove() { return mNavigationBarCanMove; } void updateConfigurationAndScreenSizeDependentBehaviors() { final Resources res = getCurrentUserResources(); mNavigationBarCanMove = mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight && res.getBoolean(R.bool.config_navBarCanMove); mAllowSeamlessRotationDespiteNavBarMoving = res.getBoolean(R.bool.config_allowSeamlessRotationDespiteNavBarMoving); }