Android 屏幕适配

android 中的屏幕适配是一个老生常谈的问题,也是一个经久不衰的话题,同时随着android 生态的不断发展,适配方案也不断进行了调整,今天我们就来聊一聊android中的适配到底有哪些奥秘。

为什么要进行屏幕适配

Android系统经过十几年的发展,已然成为主流系统之一,同时作为开源系统,其允许各个手机厂商按照自己的喜好去定制系统,因此在此基础上出现了各个手机厂商的专属系统,比如:小米的MIUI系统,华为的EMUI系统,OPPO的ColorOS系统,VIVO的Funtouch OS系统,众多的系统加之每年不断的新品推出,使android手机市场出现了一派欣欣向荣的现象,各个手机厂商不断推出新的手机品牌,各种尺寸屏幕手机,各种分辨率手机充斥在手机市场,导致android系统的手机碎片化非常严重,如下图所示:

在这里插入图片描述

Android 手机严重的碎片化导致了一个问题,即在开发android APP的时候,必须要考虑适配的问题,其基本的含义就是开发出来的APP能够正常的在众多的手机上面使用,不会出现错位,失真,文字忽大忽小等等的问题。

什么是屏幕适配

屏幕适配顾名思义就是针对不同的手机屏幕做合理的呈现展示,再专业一点的说法就是根据不同的手机尺寸、不同的手机屏幕分辨率去进行合理的代码编写以达到同一套代码生成的APP能够满足在众多手机上面呈现出同样的展示效果。

如何进行屏幕适配

在开始讲解如何进行屏幕适配之前,我们先要弄明白几个名词的含义。

名词一:屏幕尺寸
屏幕尺寸指的是屏幕的物理尺寸,单位为英寸,和我们熟知的物理单位换算公式为:
1英寸 = 2.54厘米。而在手机上,我们也会经常听到英寸单位,目前市面上面流行的手机尺寸5.X英寸、6.X英寸居多。同时需要说明的是手机上面所说的手机英寸是以手机的对角线来计算的。

名词二:手机分辨率(屏幕分辨率)
手机分辨率也是我们经常听到的名称,其实更专业一点的叫法是屏幕分辨率,通常情况下常见的屏幕分辨率有 320x480 480x800 720x1080 1080x1920 1080x2160 1440x2960等等。其中第一个数字代表的是横向(宽),第二个数字代表的是纵向(高),屏幕分辨率的基本单位是像素,即PX。假设现在有一个手机的屏幕分辨率为1080*1920,即意味着在这个手机横向上面有1080个像素点,在纵向上有1920个像素点,注意,像素是矢量单位。

名词三:dp/dip(像素密度)
这是android官方建议使用的单位,使用此单位可以在一定程度上满足众多机型适配的需要,既然它有如此重要的能力,那么我们首先就得了解dp到底是怎么一回事。dp/dip中文名为像素密度,它与手机的屏幕尺寸和屏幕分辨率没有直接的关系,但是却有着间接关系。讲解dp之前,我们需要知道另外一个单位PPI。关于PPI,这里就不展开讲解,感兴趣的朋友可以去看看我上一篇博客。PPI的计算公式为:

而这个公式里面的长度/宽度像素数对应的就是我们的屏幕分辨率,对角线英寸数对应的就是我们的屏幕尺寸,通过这个公式我们就能很轻易的算出ppi。那么ppi和dp又是什么关系呢?其实dp是Android基于物理设备的ppi抽象出来的一个单位。它是以160dpi的屏幕为基准定义的,在160dpi的屏幕的屏幕上1dp=1px,那么我们就可以得出其换算公式: 1dp=(屏幕ppi/ 160)px。

现在我们举个例子来验证一下:

手机型号(Redmi K30 5G):屏幕分辨率 10802400 6.67英寸。对应结果的ppi为 ppi = 395,最终1dp = 2.5px。现在有一个100dp的位图,占据整个横向的比例为:1002.5/1080*100%=23%

手机型号(vivo Y3s):屏幕分辨率 7201544 6.35英寸。对应结果的ppi为 ppi = 268,最终1dp = 1.7px。现在有一个100dp的位图,占据整个横向的比例为:1001.7/720*100%=23%

注意,所有的取值都是取整

看见没有,两个完全不同的手机,不同的屏幕分辨率,不同的尺寸,但是最终相同dp的位图占据的百分比却是一样的,这就是dp的魅力。

名词四:density(1dp占据当前设备多少像素)
根据前面dp的讲解,其实我们不难推断出:
density = ppi/160。由于手机屏幕分辨率与手机尺寸的不同,导致每个手机的density的最终结果值也不一样。而由于我们采用的都是dp作为单位,所以我们得知道我们手机屏幕的总dp是多少,总dp的计算公式为:
手机屏幕的总dp = 屏幕的总px / density。再回到上面的例子,同样分辨率但是不同尺寸的手机最终的density不同,而因为屏幕的总px相同,所以导致手机的总dp不同,于是就会出现屏幕适配问题。既然我们想保证手机屏幕的总dp不变,而屏幕的总px是可变的,那么我们就只能动态去改变density的值,而不能按照ppi/160的值来计算density。

介绍完了几个比较重要的名词,下面我们就开始进入正题了,屏幕适配的方案有很多种,我选取了几种目前比较流行的来讲解,这几种没有好坏之分,需要根据自己的情况选择,毕竟,适合自己的才是最好的。

屏幕适配方案一:采用系统推荐的dp单位+自适应布局+采用weight

这是官方推荐的适配方案,为什么采用dp,前面已经讲到了,这里就不再赘述了。那么,什么是自适应布局,什么又是weight呢?我们都知道,android有五大布局,即

·RelativeLayout(相对布局)
·LinearLayout(线性布局)
·AbsoluteLayout(绝对布局):被谷歌废弃
·FrameLayout(帧布局)
·TabLayout(表格布局):被GridView代替

关于五大布局的使用不是我们的重点,其中的AbsoluteLayout(绝对布局)和TabLayout(表格布局)由于一些缺陷已经被弃用,我们经常使用的是RelativeLayout(相对布局)和LinearLayout(线性布局),而恰恰这两种布局可以满足自适应的要求,究其原因是它们都是以一个View作为基准,在此基础上进行排列,这样很大程度上能够保证布局最终呈现出来的一致性。那么weight又是什么呢?其实可以将它理解为比重,它没有具体值,是根据比重值来动态计算最终呈现的样子,这样就能保证不论屏幕的尺寸是多少,最终展示出来的都是按照比例来设定的,举一个列子,并排排列两个button按钮,每个设置的比重都是1,也就意味着两个button平分整个宽度,不管屏幕的宽度是多少,最终两个按钮呈现出来的都是1:1的比例。假设将第一个button的weight设置为2,第二个button的weight还是1,那么总的值为3,那么系统会将整个屏幕的横向分为3份,其中第一个button占据2/3的距离,第二个占据1/3的比例。具体的效果大家可以通过代码自行去测试,这里就不展开显示了。

所以说通过dp +自适应布局+weight可以在很大程度上满足屏幕适配的需求,而这也是官方推荐的方式。那么,这种方式有没有缺陷呢?肯定是有的,还记得上面的例子吗?如果我们的手机屏幕分辨率为1080*1920,但是尺寸却是5英寸,这个时候展现出来的界面就会不一样了。

屏幕适配方案二:今日头条适配方案

知道了采用dp作为尺寸的不足之处后,我们就来想想有没有办法可以解决这个问题呢?
这个里面就要涉及到另外一个名词了,即density,由上面的讲解可知,如果我们想保证手机屏幕的总dp不变,而屏幕的总px是可变的,那么我们就只能动态去改变density的值,而不能按照ppi/160的值来计算density。那么如何去动态改变density的值而保证总的dp不变呢?我们首先需要看看系统是怎么计算density的
在源码TypedValue.java类中有这么几行代码

public static float applyDimension(int unit, float value,
                                   DisplayMetrics metrics)
{
   
    switch (unit) {
   
    case COMPLEX_UNIT_PX:
        return value;
    case COMPLEX_UNIT_DIP:
        return value * metrics.density;
    case COMPLEX_UNIT_SP:
        return value * metrics.scaledDensity;
    case COMPLEX_UNIT_PT:
        return value * metrics.xdpi * (1.0f/72);
    case COMPLEX_UNIT_IN:
        return value * metrics.xdpi;
    case COMPLEX_UNIT_MM:
        return value * metrics.xdpi * (1.0f/25.4f);
    }
    return 0;
}

其主要的作用就是将其他尺寸单位(例如dp,sp)转换为像素单位px。现在我们来测试一下,举个例子:
例1:设计图总宽度为375dp,屏幕宽度为1080px,可以得出density,1080/375=2.88。假如一个view为60dp,60dp算成px就是 60dp*2.88=172.8px,所占屏幕宽度比为 172.8/1080=0.16

例2:设计图总宽度为375dp,屏幕宽度为1440px,可以得出density,1440/375=3.84。假如一个view为60dp,60dp那么算成px就是 60dp*3.84=230.4px,所占屏幕宽度比为 172.8/1440=0.16。
由示例1,2可以看出,虽然屏幕宽度不一样,但是都实现了屏幕等比例适配。
那么具体的代码该怎么写呢?其实也很简单:

/**
 * author: zhoufan
 * data: 2021/6/24 14:35
 * content: 采用今日头条的理念进行屏幕适配
 */
public class ScreenAdaptationUtil {
   

    private static float sComponentDensity;
    private static float sComponentScaleDensity;

    public static void setCustomDensity(Activity activity, Application application, 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值