Android屏幕密度的深刻理解

这两个函数的区别,看不太懂,英文不行。在我的手机上,这两个函数都能获取到屏幕的宽高,代码如下:


val wm = WindowManager(this)

val metrics = wm.currentWindowMetrics

val bounds = metrics.bounds

val width = bounds.width()

val height = bounds.height()



哦呵,这里的WindowManager竟然可以直接new出来,真实神奇了!

getBounds()函数官方文档:https://developer.android.google.cn/reference/kotlin/android/view/WindowMetrics?hl=en#getBounds()

文档描述说,此方法返回的宽高是包括系统栏区域的,而Display.getSize(Point)获取的宽高不包括。getSize函数获取的宽高也可通过下面的方式获得:


final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();

  // Gets all excluding insets

  final WindowInsets windowInsets = metrics.getWindowInsets();

  Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()

          | WindowInsets.Type.displayCutout());

 

  int insetsWidth = insets.right + insets.left;

  int insetsHeight = insets.top + insets.bottom;

 

  // Legacy size that Display#getSize reports

  final Rect bounds = metrics.getBounds();

  final Size legacySize = new Size(bounds.width() - insetsWidth,

          bounds.height() - insetsHeight);

  



注:此windowManager要使用SDK自带的,不能使用jetpack中的。且此insets.width()是在API29才出来的,在低版本无法使用。

Configuration获取屏幕密度、方向、最小宽度

==========================================================================================

Configuration实例获取方式:


Configuration config = getResources().getConfiguration();



这个类上的一些感觉能用得上的属性如下:

  • densityDpi 屏幕密度

  • fontScale 字体比例,实际上我发现这个并不是我们之前理解的那个字体密度比例,不论我如何在设置中修改字体大小,它的值始终是1。

  • locale 语言环境

  • mcc IMSI MCC(移动国家/地区代码)

  • mnc IMSI MNC(移动网络代码)

  • orientation 屏幕的总体方向

  • screenWidthDp 可用屏幕空间的当前宽度,以dp为单位。

  • screenHeightDp 可用屏幕空间的当前高度,以dp为单位。经实验,我发现这个值并不是屏幕的完整高,应该是扣掉了系统状态栏的高度了。

  • smallestScreenWidthDp 应用程序在正常操作中将看到的最小屏幕尺寸,这是什么意思呢?意思是不管你是横屏还是竖屏显示,它始终是最小的那条边的尺寸,比如1080 x 1920的手机,竖屏时宽是1080,最小宽,1080px为360dp,当横屏时,高为1080px,最小宽的值还是这个1080px对应的360dp。

代码示例如下:


resources.configuration.apply {

    Timber.i("densityDpi = ${this.densityDpi}")

    Timber.i("screenWidthDp = ${this.screenWidthDp}")

    Timber.i("screenHeightDp = ${this.screenHeightDp}")

    Timber.i("smallestScreenWidthDp = ${this.smallestScreenWidthDp}")

    Timber.i("orientation = ${if (this.orientation == Configuration.ORIENTATION_LANDSCAPE) "横屏" else "竖屏"}")

}



Context.getDisplay()

===================================================================================

Display:提供一个逻辑显示的关于大小和密度的信息。

Display获取方式:


context.getWindowManager().getDefaultDisplay() // 在API30版本过时

context.getDisplay() // API30才出来的函数

DisplayManager.getDisplay(displayId)

DisplayManager.getDisplays()

DisplayManager.getDisplays(category)



示例如下:


windowManager.defaultDisplay?.let {

                Timber.i("displayId = ${it.displayId}")

                Timber.i("name = ${it.name}")

                Timber.i("width = ${it.width}")   // 过时,推荐WindowMetrics.getBounds()

                Timber.i("height = ${it.height}") // 过时,推荐WindowMetrics.getBounds()

                val metrics = DisplayMetrics()

                it.getMetrics(metrics) // 过时,推荐WindowMetrics.getBounds()获取宽高,Configuration.densityDpi获取屏幕密度

                Timber.i("width2 = ${metrics.widthPixels}")

                Timber.i("height2 = ${metrics.heightPixels}")



                Timber.i("orientation = ${it.orientation}") // 过时,推荐rotation

                Timber.i("rotation = ${it.rotation}")

                Timber.i("state = ${it.state}") // 1-显示器关闭,2-显示器打开

                Timber.i("supportedRefreshRates = ${it.supportedRefreshRates.contentToString()}")



                val metrics2 = DisplayMetrics()

                it.getRealMetrics(metrics2)

                Timber.i("width3 = ${metrics2.widthPixels}")

                Timber.i("height3 = ${metrics2.heightPixels}")



                val point = Point()

                it.getRealSize(point)

                Timber.i("width4 = ${point.x}")

                Timber.i("height4 = ${point.y}")



                val rect = Rect()

                it.getRectSize(rect) // 过时,推荐WindowMetrics#getBounds()

                Timber.i("width5 = ${rect.width()}")

                Timber.i("height5 = ${rect.height()}")



                val point2 = Point()

                it.getSize(point2) // 过时,推荐WindowManager#getCurrentWindowMetrics()

                Timber.i("width6 = ${point2.x}")

                Timber.i("height6 = ${point2.y}")

            }



打印结果如下:

displayId = 0

name = 内置屏幕

width = 1080

height = 1920

width2 = 1080

height2 = 1920

orientation = 0

rotation = 0

state = 2

supportedRefreshRates = [55.55]

width3 = 1080

height3 = 1920

width4 = 1080

height4 = 1920

width5 = 1080

height5 = 1920

width6 = 1080

height6 = 1920

最后

我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了7、8年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。

其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。

不断奔跑,你就知道学习的意义所在!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值