Android 屏幕尺寸的获取与变更(Android 12)
目前适配到 12
Android 屏幕尺寸的获取与变更
一、废弃和限制
Android 12
在 Android 12 中,我们继续建议使用 WindowMetrics
,并且正在逐步废弃以下方法:
Display.getRealSize()
Display.getRealMetrics()
Android 11 中引入了 WindowMetrics
,可让开发者轻松查询与窗口相关的指标,例如,窗口的位置和大小,以及任何系统边衬区。我们在此版本中向后移植了 API,以便开发者能够利用 WindowMetrics,并继续支持旧版 Android。
可以通过 WindowManager#getCurrentWindowMetrics() 和 WindowManager#getMaximumWindowMetrics()
API 获取 WindowMetrics。
https://developer.android.google.cn/reference/android/view/WindowMetrics
Android 11
在 Android 11 中,我们引入了 WindowMetrics API
并废弃了以下方法:
Display.getSize()
Display.getMetrics()
二、WindowMetrics( android.view.WindowMetrics)
2.1、获取WindowMetrics实例
getMaximumWindowMetrics()
和getCurrentWindowMetrics()
都是WindowManager类的方法,用于获取窗口度量信息,但它们在用途和返回结果上有所区别。
-
getMaximumWindowMetrics()
:- 该方法是Android 12(API级别31)中新增的。
- 用于获取当前设备上的最大窗口度量信息,即设备屏幕的完整尺寸。
- 返回的WindowMetrics对象包含了设备屏幕的完整度量信息,包括屏幕的大小、位置和可见区域等。
- 通过调用
getMaximumWindowMetrics().getWindowMetrics()
方法,可以获取到完整的WindowMetrics对象。 Jetpack 方法 WindowMetricsCalculator.computeMaximumWindowMetrics()
同样用途
-
getCurrentWindowMetrics()
:- 该方法在Android 11(API级别30)及更高版本中可用。
- 用于获取当前窗口的度量信息,即应用程序窗口的大小、位置和可见区域等。
- 返回的WindowMetrics对象包含了当前窗口的度量信息,包括窗口的大小、位置和可见区域等。
- 通过调用
windowManager.getCurrentWindowMetrics().getWindowMetrics()
方法,可以获取到当前窗口的完整的WindowMetrics对象。 Jetpack 的 WindowMetricsCalculator.computeCurrentWindowMetrics()。
同样用途
总结而言,getMaximumWindowMetrics()
方法用于获取设备屏幕的完整度量信息,而windowManager.getCurrentWindowMetrics()
方法用于获取当前窗口的度量信息。前者提供了整个设备屏幕的度量信息,而后者提供了当前窗口的度量信息。
需要注意的是,这些方法的返回值是WindowMetrics对象,可以通过该对象获取有关窗口的详细度量信息,如窗口大小、位置和可见区域等。
2.2、API 31
windowInsets
https://developer.android.google.cn/reference/kotlin/android/view/WindowInsets
getInsetsIgnoringVisibility()
指定可见区域排除下面的哪部分(参数指定)。
getInsetsIgnoringVisibility()
方法是 WindowInsets
类的方法,它接受一个或多个参数来指定你感兴趣的插入区域类型。以下是一些常用的参数:
WindowInsets.Type.systemBars()
:指定系统栏的插入区域,包括状态栏和导航栏。WindowInsets.Type.ime()
:指定输入法编辑器(IME)的插入区域,包括软键盘。WindowInsets.Type.ime() or WindowInsets.Type.systemBars()
:同时指定输入法编辑器和系统栏的插入区域。WindowInsets.Type.navigationBars()
:指定导航栏的插入区域。WindowInsets.Type.statusBars()
:指定状态栏的插入区域。WindowInsets.Type.displayCutout()
:指定显示切口(如刘海屏或凹口屏)的插入区域。
你可以根据需要选择一个或多个参数,以获取你想要的插入区域。例如,如果你想获取系统栏和导航栏的插入区域,可以使用 WindowInsets.Type.systemBars() or WindowInsets.Type.navigationBars()
。
请注意,插入区域的可用性和行为取决于设备的硬件和系统版本。不同的设备和 Android 版本可能会提供不同的插入区域类型和行为。因此,在使用特定插入区域之前,建议检查设备的兼容性和测试结果。
bounds
窗口大小
三、调用
package com.example.demoblog.ui.activity
import android.content.Context
import android.graphics.Point
import android.os.Build
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.WindowInsets
import com.example.demoblog.app.base.BaseActivity1
import com.example.demoblog.databinding.ActivityMainBinding
import com.example.demoblog.viewmodel.state.MainViewModel
class MainActivity : BaseActivity1<MainViewModel, ActivityMainBinding>() {
private lateinit var binding: ActivityMainBinding
override fun initView(savedInstanceState: Bundle?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// 获取当前窗口的度量信息
val windowMetrics = windowManager.currentWindowMetrics
//窗口矩阵(窗口大小)
val windowBounds = windowMetrics.bounds
val windowWidth = windowBounds.width()
val windowHeight = windowBounds.height()
//可见区域
val insetsIgnoringVisibility =
windowMetrics.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars())
val visibleWidth: Int =
windowWidth - insetsIgnoringVisibility.left - insetsIgnoringVisibility.right
val visibleHeight: Int =
windowHeight - insetsIgnoringVisibility.top - insetsIgnoringVisibility.bottom
//getInsetsIgnoringVisibility 方法测试:
//height 2245 -> systemBars
//height 2352 -> navigationBars
//height 2293 -> statusBars
//通过上面三个部分得出 navigationBars = 2293 - 2245 = 48,statusBars = 2352 - 2245 = 107
//这与直接获取状态栏的方法getStatusBarHeight对应
// 获取屏幕的密度
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
val screenDensity = displayMetrics.density
// 打印窗口度量信息
println("================================R+")
println("Window Bounds: $windowBounds")
println("Screen Size: $windowWidth x $windowHeight")
println("Visible Area: $visibleWidth x $visibleHeight")
println("Screen Density: $screenDensity")
} else {
//获取屏幕和可见窗口大小的方法,第一种
val display = windowManager.defaultDisplay
// 创建 Point 对象
val point = Point()
// 获取实际的物理尺寸(包含状态栏和导航栏高度)
display.getRealSize(point)
val screenWidthPixels = point.x
val screenHeightPixels = point.y
// 获取窗口可用的尺寸(不包含状态栏和导航栏)
display.getSize(point)
val windowWidthPixels = point.x
val windowHeightPixels = point.y
// 打印窗口度量信息
println("================================R-")
println("Screen Size: $screenWidthPixels x $screenHeightPixels")
println("Visible Area: $windowWidthPixels x $windowHeightPixels")
//获取屏幕和可见窗口大小的方法,第二种
val displayMetrics = DisplayMetrics()
// 获取实际的物理尺寸(包含状态栏和导航栏高度)
display.getRealMetrics(displayMetrics)
val screenWidthPixels2 = displayMetrics.widthPixels
val screenHeightPixels2 = displayMetrics.heightPixels
// 获取窗口可用的尺寸(不包含状态栏和导航栏)
display.getMetrics(displayMetrics)
val windowWidthPixels2 = displayMetrics.widthPixels
val windowHeightPixels2 = displayMetrics.heightPixels
val screenDensity = displayMetrics.density
// 打印窗口度量信息
println("================================R-")
println("Screen Size: $screenWidthPixels2 x $screenHeightPixels2")
println("Visible Area: $windowWidthPixels2 x $windowHeightPixels2")
println("Screen Density: $screenDensity")
}
println("======")
println("getStatusBarHeight=${getStatusBarHeight(this)}")
println("getNavigationBarHeight=${getNavigationBarHeight(this)}")
}
/**
* 获取状态栏高度
*
* @param context
* @return
*/
fun getStatusBarHeight(context: Context): Int {
val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android")
return context.resources.getDimensionPixelSize(resourceId)
}
/**
* 获取导航栏高度
*
* @param context
* @return
*/
fun getNavigationBarHeight(context: Context): Int {
val resourceId =
context.resources.getIdentifier("navigation_bar_height", "dimen", "android")
return context.resources.getDimensionPixelSize(resourceId)
}
}
更多推荐
所有评论(0)