1. 首页 > 快讯

一种成本极低的Android屏幕适配方法

android中的

传统dp适配方式的缺点

dp在渲染之前会将dp转换为px。计算公式为:

px=密度* dp;

密度=dpi/160;

px=dp * (dpi/160);

DPI是根据屏幕的实际分辨率和尺寸计算的,每个设备可能会有所不同。

屏幕尺寸、分辨率和像素密度之间的关系

通常,手机的分辨率为宽x高,屏幕尺寸的单位为英寸。三者之间的关系是:

例如:屏幕分辨率为:1920*1080,屏幕尺寸为5英寸,则dpi为440。

这有什么问题吗?

假设我们的UI设计图是按照屏幕宽度360dp来设计的,那么在上述设备上,屏幕宽度实际上是1080/(440/160)=392.7dp,也就是说屏幕比设计图宽。这种情况下,即使使用dp,在不同的设备上也无法显示相同的效果。同时,也存在一些设备的屏幕宽度小于360dp的情况,这会导致按照360dp宽度开发时显示不完整。

而且,很多设备并没有按照这个规则来实现上述屏幕尺寸、分辨率和像素密度之间的关系。所以dpi值很乱,没有规律可循,导致dp适配效果不理想。

探索新的适配方式

梳理要求

首先,我们先来梳理一下我们的需求。一般我们的设计图纸都是按照固定尺寸来设计的。例如,如果您使用1920px * 1080px 的分辨率进行设计,并以密度标记为3,则意味着屏幕实际上是640dp * 360dp。如果我们希望所有设备上的显示完全一致,其实是不现实的,因为屏幕长宽比并不是固定的。 16:9、4:3,甚至其他长宽比层出不穷。不同的长宽比,不可能呈现出完全一致的显示效果。但通常,我们只需要在一维上进行调整:宽度或高度。例如,如果我们的feed 上下滑动,我们只需要保证它在所有设备上在宽度维度上显示一致即可。再比如不支持上下滑动的页面。那么就需要保证在这个高维度下显示是一致的,特别是在某些设备上不会出现显示不完整的情况。同时考虑到适配基本都是以dp为单位进行的,如果新方案不支持dp,那么迁移成本将会非常高。

一种成本极低的Android屏幕适配方法

因此,总体要求总结如下:

支持一维适配:宽度或高度,保持该尺寸与设计一致;

支持dp和sp单位,将迁移成本控制在最低。

寻找兼容性突破

dp 和px 的换算公式:px=dp * 密度

可见,如果设计宽度为360dp,我们要保证在所有设备上计算出的px值正好是屏幕宽度,那么我们只能修改密度值。

通过阅读源码我们可以知道,density是DisplayMetrics中的一个成员变量,通过Resources#getDisplayMetrics可以获取DisplayMetrics实例,而Resouces则可以通过Activity或Application的Context获取。

首先我们先熟悉一下DisplayMetrics中与适配相关的几个变量:

DisplayMetrics#密度就是上面提到的密度

DisplayMetrics#密度Dpi就是上面的dpi

DisplayMetrics#scaledDensity 字体的缩放因子。通常它等于密度,但是调整系统字体大小会改变这个值。

那么所有的dp和px转换都是通过DisplayMetrics中的相关值计算出来的吗?

首先我们看一下布局文件中dp的转换。最后调用TypedValue#applyDimension(intunit,floatvalue,DisplayMetricsmetrics)进行转换:

这里使用的DisplayMetrics 是从Resources 中获取的。

我们再看一下图像的解码,BitmapFactory#decodeResourceStream方法:

一种成本极低的Android屏幕适配方法

可见性也是根据DisplayMetrics 中的值计算的。

当然,还有其他dp转换场景,基本都是通过DisplayMetrics计算的,这里不再详述。因此,要满足上述要求,我们只需要修改DisplayMetrics中与dp转换相关的变量即可。

最终计划

下面假设设计图的宽度为360dp,并适配宽度尺寸。

那么适配后的密度=设备的真实宽度(单位px)/360。接下来我们只需要修改我们在系统中计算的密度即可。代码实现如下:

同时在Activity#onCreate方法中调用。代码比较简单,不涉及调用系统非公开的API,所以理论上不会影响app的稳定性。

所以修改之后,推出了灰度测试的版本。稳定性符合预期。没有因此导致崩溃,但是我们收到很多反馈说字体太小:

原因是在上面的适配中,我们忽略了DisplayMetrics#scaledDensity 的特殊性,将DisplayMetrics#scaledDensity 和DisplayMetrics#density 设置为相同的值。结果有用户在系统中修改了字体大小,失败了,但是我们原来的scaledDensity也不能直接使用。如果直接使用,有些文字可能会超出显示区域。因此,我们可以通过计算之前的scaledDensity与密度的比值来得到当前的scaledDensity,如下:

不过测试后又发现了一个问题,那就是如果在系统设置中切换字体,然后返回应用程序,字体并没有改变。所以要监听字体切换,只需调用Application#registerComponentCallbacks注册onConfigurationChanged来监听即可。

所以最终的解决方案如下:

当然,上面的代码只适配了360dp的设计宽度。如果想适应高维度,可以扩展代码。

Showcase

适配前后设计图对比:

各模型适配后的显示效果:

用户评论

荒野情趣

终于不用担心不同手机分辨率了!这种方法真是太棒了

    有12位网友表示赞同!

玩味

极低成本?这让我更加好奇它的原理是什么!

    有7位网友表示赞同!

浅笑√倾城

分享一下详细的操作步骤呗,我也想试试这个适配方式

    有14位网友表示赞同!

冷眼旁观i

Android屏幕适配一直是老问题了,期待这种新方式能解决这个问题

    有13位网友表示赞同!

执笔画眉

有没有什么缺点呢?总觉得太完美了反而令人担忧

    有8位网友表示赞同!

花容月貌

如果真的能做到极低成本,那开发效率肯定会大幅提升

    有13位网友表示赞同!

七级床震

让我来试试这个方案!希望效果能像文章描述的那么好

    有7位网友表示赞同!

醉婉笙歌

这种方法是不是只能适配Android手机?期待更多平台的支持

    有5位网友表示赞同!

∞◆暯小萱◆

终于不用再折腾复杂的布局代码了,太省心啦!

    有18位网友表示赞同!

爱你心口难开

希望能详细说明一下如何实现"极低成本"的效果

    有8位网友表示赞同!

烟雨离殇

这篇文章提到的技巧我之前也尝试过,效果确实不错!

    有13位网友表示赞同!

我没有爱人i

这种方法对程序的运行速度有什么影响呢?

    有19位网友表示赞同!

嗯咯

听起来很新颖,期待看到更多针对这个适配方式的应用案例!

    有15位网友表示赞同!

凉笙墨染

感觉这个方法可以应用到很多类型APP中去

    有15位网友表示赞同!

清原

学习一下这方面的新技术,提升自己的开发能力

    有18位网友表示赞同!

百合的盛世恋

希望这种低成本适配方式能够被广泛应用

    有8位网友表示赞同!

泡泡龙

这款Android屏幕适配方法是不是简单易用?

    有6位网友表示赞同!

丢了爱情i

我试过很多屏幕适配方案,都感觉效果一般般,期待这个方法能带来突破

    有20位网友表示赞同!

本文采摘于网络,不代表本站立场,转载联系作者并注明出处:https://www.iotsj.com//kuaixun/5798.html

联系我们

在线咨询:点击这里给我发消息

微信号:666666