Android最全Android屏幕密度的深刻理解,2024年最新移动端页面开发流程

最后

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

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

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

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

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

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

后来想了一下,修改dpi可以这样理解,默认的dpi是真实的dpi,也就是代表1英寸有多少个像素的,当你修改屏幕最小宽度后,其实1英寸有多少个像素是固定了不可能再变了的,修改只是模拟而已,是模拟的行为,比如宽为1080,标准密度是480,1dp = 3px,则宽度为360dp,现在把最小宽度改为1080dp,则1dp = 1px,密度为160,此时的1英寸中包含有160个像素,这是不可能的,因为真实的话是包含有480个,所以这里密度为160的1英寸是模拟的1英寸,是比原来小3倍的1英寸,所以,最小宽度改为1080dp后,可以理解为手机的英寸变多了(手机尺寸变大了),当然了,这只是模拟的或者想像的变大了,其实并没有变大,此时的1英寸并不是真实物理上的1英寸了,它是物理1英寸的三分之一大小,因为物理1英寸是装有480像素的,而它只有160,480 / 160 = 3。

所以,当你在两台分辨率相同的手机上运行同一个app时,如果发现显示效果不一样,则你要想到应该是它们的dpi不相同导致的,你可以到设置里面修改最小宽度,改成一样的,这样效果肯定就一样了。

如果是分辨率一样,密度也一样,但是字体大小看起来不一样,则你要想到应该是字体密度比例不相同导致的,你可以到设置里面修改字体大小,调到字体密度比例一样时,效果肯定就一样了。

在公司的一台定制机上,分辨率是1080P的,默认最小宽度是360dp,可以改到160dp,但是在小米6和华为mate30上,相同的分辨率,默认最小宽也是360dp,但是修改时最小只能改到320dp。改大时,华为mate30可以改到1080dp没问题,而小米6改1080dp后,直接黑屏重启了,而且再也起不来了,自动进入了Recovery模式,估计要清除数据才能恢复了。所以这个最小宽度不要随便设置,有风险!!

常见分辨率:

drawable-xhdpi 文件夹: 超高密度屏幕:dpi = 320dp,scale = 2.0,分辨率:720 x 1280

drawable-xxhdpi文件夹: 超超高密度屏幕:dpi = 480dp,scale= 3.0,分辨率:1080 x 1920

为什么按照720 x 1280写的界面,只要单位是dp,就能在1080 x 1920中完美适配呢?这是因为他们的dp数量是一个的:

720 x 1280

宽度:720 / 2 = 360dp

高度:1280 / 2 = 640dp

1080 x 1920

宽度:1080 / 3 = 360dp

高度:1920 / 3 = 640dp

所以,虽然他们的分辨率不一样,但是只要确保720P的手机密度为320dp,1080P的手机密度为480dp,则他们宽高的dp数是一样的。其实高度的dp数不一样影响不大,因为高度上可以增加垂直滚动,上下滚动就好了,关键宽度的dp数,如果宽度上dp数一样,则适配就是完美的,所以对于适配,一般看看手机设置里的最小宽度的dp数量是不是一样的就知道了,比如在720P或1080P手机上,最小宽度dp为360dp,而在我的另一台小米手机,它的宽度最小dp为411dp,假如美工给你的图是以720P设计的,在宽度上放了各种控件,放满宽度最多也就使用360个dp,假设用的是线性布局水平排序,当运行到411dp的手机上时,你会发现手机右侧多了很多空白,因为你的空间总共的宽最多360dp,而手机有411dp。所以在做开发时,尽量不要写这种太绝对的布局,比如标题栏,标题在中间,左右两侧有图标,使用相对布局就比较好,运行到360dp和411dp上,能保证标题栏各位控件的相对位置,只是效果上,411dp的手机标题栏的标题和左右两边的图标距离看着会感觉比较大一些。

WindowMetrics.getBounds()获取屏幕宽高

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


DisplayMetrics dm = new DisplayMetrics();

activity.getWindowManager().getDefaultDisplay().getMetrics(dm);



通过这种方式也能获取到一个DisplayMetrics对象,但是我们发现getMetrics函数已经过时了,推荐使用WindowMetrics.getBounds()获取应用程序窗口区域的尺寸,使用Configuration.densityDpi获取当前密度。

于是我就查了WindowMetrics的官方文档,上面推荐了两各方式获取此对象的实例,如下:


mWindowManager.getCurrentWindowMetrics()

mWindowManager.getMaximumWindowMetrics()



细看WindowMetrics类的完全形式为:androidx.window.WindowMetrics,这不是SDK里面的类,这是Jetpack组件里面的,所以要想使用这个类,需要引入依赖,如下:


implementation "androidx.window:window:1.0.0-alpha02"



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


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}")




**【延伸Android必备知识点】**

![](https://img-blog.csdnimg.cn/img_convert/0793c43d64ce859667f4931522447115.webp?x-oss-process=image/format,png)

**【Android部分高级架构视频学习资源】**

**Android精讲视频学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!

**任何市场都是优胜略汰适者生存,只要你技术过硬,到哪里都不存在饱和不饱和的问题,所以重要的还是提升自己。懂得多是自己的加分项 而不是必须项。门槛高了只能证明这个市场在不断成熟化!**另外一千个读者就有一千个哈姆雷特,所以以上只是自己的关键,不喜勿喷!

如果你是卡在缺少学习资源的瓶颈上,那么刚刚好我能帮到你。欢迎关注会持续更新和分享的。



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

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

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

证明这个市场在不断成熟化!**另外一千个读者就有一千个哈姆雷特,所以以上只是自己的关键,不喜勿喷!

如果你是卡在缺少学习资源的瓶颈上,那么刚刚好我能帮到你。欢迎关注会持续更新和分享的。



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

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

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

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值