Android中获取当前设备的宽高与屏幕密度等数据的工具类

文章目录


ScreenSizeUtil

在 Android 开发中,获取屏幕尺寸是高频需求,但不同系统版本(尤其是 API 30 前后)的 API 差异、状态栏 / 导航栏的扣除逻辑、分屏 / 折叠屏适配等问题,很容易导致尺寸计算错误。本文分享一套兼容所有 Android 版本的屏幕尺寸工具类,支持获取设备物理尺寸、应用可用尺寸,还能单独获取状态栏 / 导航栏高度,解决日常开发中 99% 的屏幕尺寸适配问题

完整工具类

kotlin 复制代码
object ScreenSizeUtil {


    /**
     *  @describe: 获取当前设备的宽高,包含了状态栏、导航栏
     *   1.忽略了分屏、画中画,始终返回当前设备最大尺寸
     *   2.折叠屏时返回展开态时的设备最大尺寸
     *  @params:
     *  @return: Pair<Int,Int> 宽度与高度
     */

    fun getScreenDevicesSize(context: Context): Pair<Int, Int> {

        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { //30以上的适配
            val bounds = context.windowManager.maximumWindowMetrics.bounds //获取当前设备的屏幕信息
            bounds.height()
            Pair(bounds.width(), bounds.height())
        } else { //低版本适配

            //方法1 获取实际的物理尺寸,包含状态栏跟导航栏
            val display = context.displayManager.getDisplay(Display.DEFAULT_DISPLAY)
            val physicalWidth = display.mode.physicalWidth
            val physicalHeight = display.mode.physicalHeight
            Pair(physicalWidth, physicalHeight)

            //方法2 获取实际的物理尺寸,包含状态栏跟导航栏
            /*val display = context.windowManager.defaultDisplay
            val point = Point()
            display.getRealSize(point)
            Pair(point.x,point.y)*/
        }
    }


    /**
     *  @describe: 获取应用可用高度,减去了状态栏、导航栏
     *        1.返回画中画、分屏中当前窗口占用的区域,
     *        2.折叠屏时返回折叠态的小屏高度
     *  @params:
     *  @return: Pair<Int,Int> 宽度与高度
     */
    fun getAppUsableSize(context: Context): Pair<Int, Int> {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val windowManager =
                context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
            val windowMetrics = windowManager.currentWindowMetrics //获取当前窗口的信息
            val insets = windowMetrics.windowInsets
                .getInsetsIgnoringVisibility(android.view.WindowInsets.Type.systemBars()) //排除系统插入区域(状态栏+导航栏)后的可见区域
            // 应用高度 = 窗口高度 - 状态栏高度 - 导航栏高度
            val height = windowMetrics.bounds.height() - insets.top - insets.bottom
            val width = windowMetrics.bounds.width() - insets.left - insets.right

            Pair(width, height)
        } else {
            // 方法1 获取当前窗口的宽高
            val decorView = (context as android.app.Activity).window.decorView
            val outRect = Rect()
            decorView.getWindowVisibleDisplayFrame(outRect)
            Pair(outRect.right - outRect.left, outRect.bottom - outRect.top)


            //方法2 获取当前窗口的宽高
            /* val meterics = DisplayMetrics()
             context.windowManager.defaultDisplay.getMetrics(meterics)
             Pair(meterics.widthPixels,meterics.heightPixels - getStatusBarHeight(context)) //老版本默认包含状态栏*/

            //方法3.获取当前窗口的宽高
            /*val display = context.windowManager.defaultDisplay
            val point = Point()
            display.getSize(point)
            Pair(point.x,point.y - getStatusBarHeight(context)) //老版本默认包含状态栏*/
        }

    }

    /**
     * 获取状态栏高度
     *
     * @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)
    }

    /**
     *  @describe: 返回当前屏幕的密度
     *  @params: 上下文
     *  @return:
     */
    fun getDisplayMetrics(context: Context): Float {
        val displayMetrics = DisplayMetrics()
        context.windowManager.defaultDisplay.getMetrics(displayMetrics)
        return displayMetrics.density
    }
}
相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui