DisplayMetrics获取宽高不对

您所在的位置:网站首页 屏幕宽高 DisplayMetrics获取宽高不对

DisplayMetrics获取宽高不对

2023-08-12 05:22| 来源: 网络整理| 查看: 265

DisplayMetrics获取宽高不对 一、引言

该车机项目为宽屏显示,使用Android 9.0系统开发,分辨率为1920x720,配置navigation bar为120px,显示在左侧。

二、问题

通过如下方法拿到的屏幕高度值是576,正常应该是720。

DisplayMetrics dm = getResources().getDisplayMetrics(); int screenHeight = dm.heightPixels; 三、分析 1、dumpsys display

dumpsys display信息如下:

Logical Displays: size=2 Display 0: mDisplayId=0 mLayerStack=0 mHasContent=true mRequestedMode=0 mRequestedColorMode=0 mDisplayOffset=(0, 0) mPrimaryDisplayDevice=内置屏幕 mBaseDisplayInfo=DisplayInfo{"内置屏幕", uniqueId "local:0", app 1920 x 720, real 1920 x 720, largest app 1920 x 720, smallest app 1920 x 720, mode 1, defaultMode 1, modes [{id=1, width=1920, height=720, fps=60.000004}], colorMode 0, supportedColorModes [0], hdrCapabilities android.view.Display$HdrCapabilities@40f16308, rotation 0, density 240 (160.0 x 160.0) dpi, layerStack 0, appVsyncOff 8300000, presDeadline 9366666, type BUILT_IN, state ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, removeMode 0} mOverrideDisplayInfo=DisplayInfo{"内置屏幕", uniqueId "local:0", app 1920 x 576, real 1920 x 720, largest app 1920 x 1808, smallest app 720 x 536, mode 1, defaultMode 1, modes [{id=1, width=1920, height=720, fps=60.000004}], colorMode 0, supportedColorModes [0], hdrCapabilities android.view.Display$HdrCapabilities@40f16308, rotation 0, density 240 (160.0 x 160.0) dpi, layerStack 0, appVsyncOff 8300000, presDeadline 9366666, type BUILT_IN, state ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, removeMode 0} Display 1: mDisplayId=1 mLayerStack=1 mHasContent=false mRequestedMode=0 mRequestedColorMode=0 mDisplayOffset=(0, 0) mPrimaryDisplayDevice=HDMI 屏幕 mBaseDisplayInfo=DisplayInfo{"HDMI 屏幕", uniqueId "local:1", app 1920 x 720, real 1920 x 720, largest app 1920 x 720, smallest app 1920 x 720, mode 2, defaultMode 2, modes [{id=2, width=1920, height=720, fps=60.000004}], colorMode 0, supportedColorModes [0], hdrCapabilities android.view.Display$HdrCapabilities@40f16308, rotation 0, density 213 (213.0 x 213.0) dpi, layerStack 1, appVsyncOff 8300000, presDeadline 9366666, type HDMI, state ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, FLAG_PRESENTATION, removeMode 0} mOverrideDisplayInfo=DisplayInfo{"HDMI 屏幕", uniqueId "local:1", app 1920 x 720, real 1920 x 720, largest app 1920 x 1920, smallest app 720 x 720, mode 2, defaultMode 2, modes [{id=2, width=1920, height=720, fps=60.000004}], colorMode 0, supportedColorModes [0], hdrCapabilities android.view.Display$HdrCapabilities@40f16308, rotation 0, density 213 (213.0 x 213.0) dpi, layerStack 1, appVsyncOff 8300000, presDeadline 9366666, type HDMI, state ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, FLAG_PRESENTATION, removeMode 0}

看到mOverrideDisplayInfo中打印为1920 x 576;

2、DisplayContent

跟踪代码发现DisplayContent中会更新mOverrideDisplayInfo

frameworks\base\services\core\java\com\android\server\wm\DisplayContent.java /** * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config * changed. * Do not call if {@link WindowManagerService#mDisplayReady} == false. */ private DisplayInfo updateDisplayAndOrientation(int uiMode) { ... final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode, mDisplayId, displayCutout); final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode, mDisplayId, displayCutout); ... // We usually set the override info in DisplayManager so that we get consistent display // metrics values when displays are changing and don't send out new values until WM is aware // of them. However, we don't do this for displays that serve as containers for ActivityView // because we don't want letter-/pillar-boxing during resize. final DisplayInfo overrideDisplayInfo = mShouldOverrideDisplayConfiguration ? mDisplayInfo : null; mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId, overrideDisplayInfo);

继续跟进,发现调用的mPolicy获取的appWidth和appHeight,分别在PhoneWindowManager中的getNonDecorDisplayWidth与getNonDecorDisplayHeight实现。

3、PhoneWindowManager frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java private int getNavigationBarWidth(int rotation, int uiMode) { if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) { return mNavigationBarWidthForRotationInCarMode[rotation]; } else { return mNavigationBarWidthForRotationDefault[rotation]; } } @Override public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode, int displayId, DisplayCutout displayCutout) { int width = fullWidth; // TODO(multi-display): Support navigation bar on secondary displays. if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) { // For a basic navigation bar, when we are in landscape mode we place // the navigation bar to the side. if (mNavigationBarCanMove && fullWidth > fullHeight) { width -= getNavigationBarWidth(rotation, uiMode); } } if (displayCutout != null) { width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight(); } return width; } private int getNavigationBarHeight(int rotation, int uiMode) { if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) { return mNavigationBarHeightForRotationInCarMode[rotation]; } else { return mNavigationBarHeightForRotationDefault[rotation]; } } @Override public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode, int displayId, DisplayCutout displayCutout) { int height = fullHeight; // TODO(multi-display): Support navigation bar on secondary displays. if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) { // For a basic navigation bar, when we are in portrait mode we place // the navigation bar to the bottom. if (!mNavigationBarCanMove || fullWidth height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom(); } return height; }

分析这两个方法,发现:

mNavigationBarCanMove为true且fullWidth > fullHeight的情况,认为navigation bar显示在左侧或右侧,getNonDecorDisplayWidth获取时需减掉navigation bar的宽度;而fullWidth < fullHeight时,认为navigation bar始终显示在底部,则getNonDecorDisplayHeight需减掉navigation bar的高度。

所以,我们保证上述条件满足时即可正确计算应用显示的宽高。

四、实现

1、新增属性ro.vendor.navi_bar_pos配置navigation bar显示位置

device/[project]/system.prop +#navigation bar position, 1-left 2-right +ro.vendor.navi_bar_pos=1

2、配置显示navigation bar及宽高

a、device/[project]/overlay/frameworks/base/core/res/res/values/config.xml true b、device/[project]/system.prop -qemu.hw.mainkeys=1 c、device/[project]/overlay/frameworks/base/core/res/res/values/dimens.xml 120px 120px

3、PhoneWindowManager适配

--- a/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -2514,6 +2514,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } //Log.d(TAG, "wlf shortSizeDp = "+shortSizeDp); + // add start + if(SystemProperties.getInt("ro.vendor.navi_bar_pos", 0) > 0) { + mNavigationBarCanMove = true; + } + // add end mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar); @@ -5168,10 +5173,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { @NavigationBarPosition private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { + // add start + int position= SystemProperties.getInt("ro.bw.navi_bar_pos", 0); + if(displayWidth > displayHeight && position > 0) { + return position; + } + // add end if (mNavigationBarCanMove && displayWidth > displayHeight) { if (displayRotation == Surface.ROTATION_270) {

该修改主要是保证mNavigationBarCanMove为true,还有就是navigationBarPosition根据显示宽高调整位置。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3