Android 一种非常好用的Android屏幕适配

摘要:
因为px适配基本上在互联网上使用,也就是说,每个屏幕分辨率设备都需要定义一组dimensions.xml文件。创建相应dimensions.xml文件插件(稍后讨论)的作者AndroidAdu也表示,他曾在他所在的两家大公司实习。最全面的解决方案是Android屏幕适配解决方案。px和dp自适应的原理。px自适应原理:dp自适应原理与px自适应原理相同。为什么dp自适应优于px自适应?

前言

网上关于屏幕适配的文章已经铺天盖地了,为什么我还要讲?因为网上现在基本都是使用px适配,即每种屏幕分辨率的设备需要定义一套dimens.xml文件。再加上有些手机还有虚拟按键(例如华为),这样就还需要每个有虚拟按键的设备加多一套dimens.xml文件,再加上平板那些你会发现dimens.xml文件所占的体积已经超过2M了!这绝对不是我们想要的。

我这里要讲的是使用dp来进行适配(Google推荐的也是这种方式),使用这种方式项目中多套dimens.xml文件才占几百K,而且根本不用考虑虚拟按键的问题。这种方案已经在自己多个项目中应用过了,经过几十台手机测试过,基本不会出现适配有问题的情况。制作生成对应dimens.xml文件插件的作者(后面会讲)android阿杜也说过他在待过的两家大公司实践过,所以请放心使用。

为什么要进行Android屏幕适配?

关于为什么要进行Android屏幕适配,什么是dp、dpi这些概念我就不去一一讲解了,网上很多文章。这里我推荐几篇讲的比较好的:

px与dp适配的原理

  • px适配原理:
    根据设备屏幕的分辨率各自写一套dimens.xml文件,然后根据一个基准分辨率(例如720x1080),将宽度分成720份,取值为1px——720px,将高度分成1080份,取值为1px——1080px。生成各自dimens.xml文件对应的值。

  • dp适配原理:
    dp适配原理与px适配一样,区别就在于px适配是根据屏幕分辨率,即拿px值等比例缩放,而dp适配是拿dp值来等比缩放而已。

问题:

  1. 既然原理都一样,都需要多套dimens.xml文件,为什么说dp适配就比px适配好呢?
    因为px适配是根据屏幕分辨率的,Android设备分辨率一大堆,而且还要考虑虚拟键盘。而dp适配无论手机屏幕的像素多少,密度比值多少,80%的手机的最小宽度dp值(widthPixels / density)都为360dp,这样就大大减少了dimens.xml文件。

  2. px适配会根据设备的分辨率去找对应的dimens.xml文件(如下图,运行在分辨率为1920x1080的手机上,系统会自动找到对应的values-1920x1080文件),那dp适配呢?


     
    Android 一种非常好用的Android屏幕适配第1张
     

dp适配也是一样的,只不过dp适配是根据“最小宽度(Smallest-width)限定符”来找的,需要注意的是“最小宽度”是不区分方向的,即无论是宽度还是高度,哪一边小就认为哪一边是“最小宽度”。所以如果当前设备最小宽度(以 dp 为单位)为400dp,那么系统会自动找到对应的values-sw400dp文件夹下的dimens.xml文件,如图

 
Android 一种非常好用的Android屏幕适配第2张
 

获取设备最小宽度代码,

        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int heightPixels = dm.heightPixels;
        int widthPixels = dm.widthPixels;
        float density = dm.density;
        float heightDP = heightPixels / density;
        float widthDP = widthPixels / density;
        float smallestWidthDP;
        if(widthDP < heightDP) {
            smallestWidthDP = widthDP;
        }else {
            smallestWidthDP = heightDP;
        }

使用步骤

1、以某一widthDP为基准,生成所有设备对应的dimens.xml文件

生成这些文件当然不会手动去写,网上已经有大神android阿杜提供了自动生成工具。

工具使用步骤:

  1. 在Android Studio中安装ScreenMatch插件,如图:
 
Android 一种非常好用的Android屏幕适配第3张
 
  1. 在项目的默认values文件夹中需要一份dimens.xml文件
    我在github源码已经提供了一份,直接复制过来即可。
 
Android 一种非常好用的Android屏幕适配第4张
 

github地址:ScreenAdaptation

  1. 执行生成
    插件安装好后,在项目的任意目录或文件上右键,选择ScreenMatch选项。如图:
 
Android 一种非常好用的Android屏幕适配第5张
 

然后选择在哪个module下执行适配。
即基于哪个module下的res/values/dimens.xml文件作为基准dimens.xml文件,生成的其他尺寸dimens.xml文件放在哪个module下。

 
Android 一种非常好用的Android屏幕适配第6张
 

点击确定就会执行生成命令,如下代表生成成功。

 
Android 一种非常好用的Android屏幕适配第7张
 

然后再看看res目录下会自动生成一堆dimens.xml文件,如下:

 
Android 一种非常好用的Android屏幕适配第8张
 

通过上面的步骤就已经生成了所有设备对应的dimens.xml文件。

因为默认生成的是下列最小宽度dp的dimens.xml文件
384,392,400,410,411,480,533,592,600,640,662,720,768,800,811,820,960,961,1024,1280,1365,如果不需要或者需要增加某些dp值的dimens.xml文件,则需要修改配置文件,即screenMatch.properties文件(修改前先删除之前生成的全部dimens.xml文件)。配置文件在我们执行完成上面的命令后,会在项目的目录下自动生成,如下:

 
Android 一种非常好用的Android屏幕适配第9张
 

打开文件,修改下面的值即可。如下只需要适配384,392,400,410,411的值,不需要适配480,533,592,600,640,662,720,768,800,811,820,960,961,1024,1280,1365的值

 
Android 一种非常好用的Android屏幕适配第10张
 

其中base_dp=360代表widthDP基准值,一般都是360dp,不建议更改,除非你对屏幕适配原理有深刻的见解。

当然!这些步骤你可以全部都不用做。直接复制我github上的各个dimens.xml文件到你项目即可!这些都是我在真实项目中使用的。

2、根据设计图标注,在布局写上对应的值。

在安卓中,系统密度为160dpi的中密度手机屏幕为基准屏幕,即320×480的手机屏幕。在这个屏幕中,1dp=1px。320x480分辨率对应的其他分辨率的比例如下:

 
Android 一种非常好用的Android屏幕适配第11张
image.png

图片来源:UI设计师不可不知的安卓屏幕知识

所以,如果UI给的是720x1280分辨率的图, 那么dp = px / 2, 给的是1080x1920分辨率的图,那么 dp = px / 3,即根据比例即可。

举例:UI在720x1280上做的图,其中一个按钮的宽高分辨为:宽720px,高为100px,字体大小为30px,在布局中则这样使用:

    <Button
        android:layout_width="@dimen/dp_360"
        android:layout_height="@dimen/dp_50"
        android:textSize="@dimen/sp_15"/>

代码中动态设置dp或sp:
如果需要在代码中动态设置dp或sp,则需要通过getDimension()方法获取对应资源文件下的dp或sp值再设置(具体参考github上的demo)。如下:

        /*获取sp值*/
        float pxValue = getResources().getDimension(R.dimen.sp_15);//获取对应资源文件下的sp值
        int spValue = ConvertUtils.px2sp(this, pxValue);//将px值转换成sp值
        mTvShowParams.setTextSize(spValue);//设置文字大小

        /*获取dp值*/
        float pxValue2 = getResources().getDimension(R.dimen.dp_360);//获取对应资源文件下的dp值
        int dpValue = ConvertUtils.px2dp(this, pxValue2);//将px值转换成dp值

怎么适配其他module?

  • 问题:在项目的其他module中怎么实现适配?难道也要多套dimens?
  • 解决:并不需要多套dimens,只需要在values文件夹下有一套与app module一样的dimens文件即可达到适配。因为经过编译,所有module中的dimen数据都会统一归类到主module(即app module)中的values/dimens.xml文件中了,然后系统又会根据你设置的值去找对应values-swxxxdp文件夹下的dimens.xml文件中的值。
  • 验证:在项目中建一个module,然后随便取一个dimens.xml文件中的值进行打印,分别运行在不同widthDP的设备上(用模拟器即可)观察打印的结果发现确实是这样的。

最后非常感谢大神android阿杜提供的插件,具体的dp适配与插件原理可以去看看他写的文章。

github地址:ScreenAdaptation

参考资料:

免责声明:文章转载自《Android 一种非常好用的Android屏幕适配》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Redis 下载与安装(Windows版)在SpringBoot中使用flyway进行数据库版本管理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[Swift]遍历集合类型(数组、集合和字典)

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/ )➤GitHub地址:https://github.com/strengthen/LeetCode➤原文地址:https://...

jq+layui 总结1

1、//获取当前时间*24小时制var myDate = new Date(); var createTime=myDate.toLocaleString('chinese', { hour12: false }); 2、//获取select中选中的值var temType = $("#temType option:selected").text(); 3...

线性函数拟合R语言示例

线性函数拟合(y=a+bx) 1.       R运行实例 R语言运行代码如下:绿色为要提供的数据,黄色标识信息为需要保存的。 x<-c(0.10,0.11, 0.12, 0.13, 0.14, 0.15,0.16, 0.17, 0.18, 0.20, 0.21, 0.23) y<-c(42.0,43.5, 45.0, 45.5, 45.0,...

原创-PromQL语法

匹配标签值时可以是等于,也可以使用正则表达式。总共有下面几种匹配操作符: =:完全相等 !=: 不相等 =~: 正则表达式匹配 !~: 正则表达式不匹配 Prometheus的4种数据类型如下。·瞬时向量(Instant vector):一组时间序列,每个时间序列包含单个样本,它们共享相同的时间戳。也就是说,表达式的返回值中只会包含该时间序列中最新的一...

字符串截取及切割,正则表达式,expect预期交互

                                        字符串截取及切割,正则表达式,expect预期交互 案例1:字符串截取及切割 案例2:字符串初值的处理 案例3:expect预期交互 案例4:使用正则表达式 1案例1:字符串截取及切割 1.1问题 使用Shell完成各种Linux运维任务时,一旦涉及到判断、条件测试等相关操作时...

WAI-ARIA无障碍网页资料

西门小白菜 我很骄傲,因为我是小白菜一枚! WAI-ARIA无障碍网页资料 一、ARIA是啥?      WAI-ARIA指无障碍网页应用。主要针对的是视觉缺陷,失聪,行动不便的残疾人以及假装残疾的测试人员。尤其像盲人,眼睛看不到,其浏览网页则需要借助辅助设备,如屏幕阅读器,屏幕阅读机可以大声朗读或者输出盲文。而ARIA就是可以让屏幕阅读器准确识别...