看了一定会有收获的屏幕适配全解析

作者: 付凯强 | 来源:发表于2018-04-28 22:23 被阅读330次

    1. 序言

    • 屏幕适配:到底哪一种屏幕适配最合适,仁者见仁智者见智.今天我依然推荐dimens基于px的适配.
    • 屏幕尺寸:屏幕的对角线的长度。
    • 屏幕分辨率:屏幕宽和高两者的像素值之积。

    2. 切图

    • 设计师切图依照1280 * 720的分辨率进行切图,既适用于更高分辨率的手机,也适用于更低分辨率的手机,而且节省资源,占用更少的空间。
    • 考虑到现在屏幕越来越大,全面屏占据了半壁江山,可以考虑更高分辨率的切图,比如1920 * 1080。

    3. 图片适配

    • 在AndroidStudio的资源目录res下有五个层级图片文件夹,分别用来存放不同分辨率的图片:
    ① drawable-ldpi :低分辨率(用的少了,一般不再用)
    ② drawable-mdpi:中分辨率
    ③ drawable-hdpi:高分辨率
    ④ drawable-xdpi:较高分辨率
    ⑤ drawable-xxdpi:超级高分辨率
    ⑥ drawable-xxxhpi:顶级分辨率
    
    • 在对应的文件夹下放置不同分辨率的图片就可以很好的对图片进行适配。

    4. 布局适配

    • 布局适配适用于手机大小不一样的手机用不同的布局,比如说创建两个文件夹:
    ① layout-800 * 480
    ② layout-1280 * 720
    ......
    
    • 手机会根据分辨率去找设定的不同大小的layout的布局。

    5. 权重适配

    • 当布局占满屏幕宽或高的时候,子布局可以使用权重适配,常见于LinearLayout线性布局中。

    6. 尺寸适配

    • 尺寸适配利用百分比的概念达到非常好的适配效果:
    以400*320为基准,以宽举例:宽分为了320份:每份1.0px,那1280*720的宽的每份就是2.25px。
    
    • 创建values-400*320文件夹,创建dimens.xml文件,设置代码如下:
    <resources>
    <dimen name="x2">2.0px</dimen>
    </resources>
    
    • 创建values-800*480文件夹,创建dimens.xml文件,设置代码如下:
    <resources>
    <dimen name="x2">3.0px</dimen>
    </resources>
    
    • 代码中使用:
    R.dimen.x2
    
    • 布局中使用:
    @dimen/x2
    

    7. 代码适配

    Button button = (Button) findViewById(R.id.bt_main_button);
    //获取手机屏幕的宽和高
    int widthPixels = getResources().getDisplayMetrics().widthPixels;
    int heightPixels = getResources().getDisplayMetrics().heightPixels;
    //给button设置宽和高
    ViewGroup.LayoutParams layoutParams = button.getLayoutParams();
    layoutParams.width = widthPixels / 2;
    layoutParams.height = heightPixels / 2;
    button.setLayoutParams(layoutParams);
    

    8. 获取屏幕参数

    • 像素 - px:
    一个小黑点就是像素。
    
    • 尺寸:
    屏幕的对角线的长度。
    
    • 分辨率:
    整个屏幕一共有多少个点,也就是像素。
    
    • 像素密度 - dpi:
    1. 每英寸中的像素数。
    2. 假如设备分辨率为320*240,屏幕长2英寸宽1.5英寸,dpi=320/2 = 240/1.5 =160。
    3. 对应于DisplayMetrics类中属性densityDpi的值。
    
    • 密度 - density:
    1. 每平方英寸中的像素数。
    2. density = dpi / 160 。
    3. 对应于DisplayMetrics类中属性density的值 。
    4. 可用于px与px与dip的互相转换 :dp = px / density 。
    
    • 设备独立像素 - dip - dp:
    - 不同设备有不同的显示效果,不依赖像素。
    - dp = px / density
    - dp = px / (dpi / 160) 
    - dpi(像素密度)为160 的设备上1dp = 1px。
    
    • 放大像素 - sp:
    用于字体显示。
    

    9. dp转px、px转dp

    public class Dp2Px {
        public static int dp2px(Context context, int dp) {
            return (int) (dp * context.getResources().getDisplayMetrics().density + 0.5);
        }
    
        public static int px2dp(Context context, int px) {
            return (int) (px / context.getResources().getDisplayMetrics().density + 0.5);
        }
    }
    
    说明:0.5 是为了避免损失精度。
    

    10. 常见设备的dp、px、density的关系

    • ldpi:
    density:0.75
    分辨率:240*320 
    关系:dp = px / 0.75
    
    • mdpi:
    density:1
    分辨率:320 * 480
    关系:dp = px / 1
    
    • hdpi:
    density:1.5
    分辨率:480 * 800
    关系:dp = px / 1.5
    
    • xhdpi:
    density:2.0
    分辨率:720 * 1280 
    关系:dp = px / 2
    
    • xxhdpi:
    density:3
    分辨率:1080 * 1920 
    关系:dp = px / 3
    

    11. 综上:

    //以1280*720为基准:
    //获取手机屏幕的宽和高
    int widthPixels = getResources().getDisplayMetrics().widthPixels;
    int heightPixels = getResources().getDisplayMetrics().heightPixels;
    //density
    float density = getResources().getDisplayMetrics().density;
    //dpi
    int densityDpi = getResources().getDisplayMetrics().densityDpi;
    //1dp = 多少px
    int px = Dp2Px.dp2px(this, 1);
    //1px  = 多少dp
    int dp = Dp2Px.px2dp(this, 1);
    
    04-30 23:29:15.606 2484-2484/com.example.testscreen E/MainActivity: widthPixels: 720
    04-30 23:29:15.606 2484-2484/com.example.testscreen E/MainActivity: heightPixels: 1280
    04-30 23:29:15.606 2484-2484/com.example.testscreen E/MainActivity: density: 2.0
    04-30 23:29:15.606 2484-2484/com.example.testscreen E/MainActivity: densityDpi: 320
    04-30 23:29:15.606 2484-2484/com.example.testscreen E/MainActivity: px:2
    04-30 23:29:15.606 2484-2484/com.example.testscreen E/MainActivity: dp:1
    

    12. 最好适配(个人观点)

    • 看了一篇android适配的博客,讲述的是尺寸适配,不过用的是dp,而不是px。
    • px适配依据的分辨率,dp适配依据的是最小宽度限定符。
    • dp适配本身也有适配的能力,从这一点看,基于dp生成values文件夹的形式还是可以考虑使用的。
    • dp适配依据的是最小宽度限定符,dpi宽和高一致的情况下,这种适配是没有问题的,遇上S9+(2960 x 1440)就出错了,高度适配不了,所以这种通过最小宽度限定符适配的方式不推荐。
    • px适配因为和分辨率挂钩,更加准确,况且也不大,只有三百多kb而已,并非如他人所说有2M ,而且直接就可以根据效果图来使用,个人推荐基于px适配而生成的values适配方法。
    • 下载地址和密码如下:
    链接:https://pan.baidu.com/s/1jLXpQXs898hzIensZKV7gg 密码:6xgs
    

    13. dimens-px 适配:

    原理:根据市面上手机分辨率的占比分析,我们把1280和720设定为一个基准,然后其他分辨率根据这个基准做适配。

    • 基准的意思(比如320*480的分辨率为基准)是:
      • 宽为320,将任何分辨率的宽度分为320份,取值为x1到x320
      • 长为480,将任何分辨率的高度分为480份,取值为y1到y480
        例如对于800*480的宽度480:
    <?xml version="1.0" encoding="utf-8"?>
    <resources><dimen name="x1">1.5/dimen>
    <dimen name="x2">3.0px</dimen>
    <dimen name="x3">4.5</dimen>
    <dimen name="x4">6.0px</dimen>
    <dimen name="x5">7.5px</dimen>
    

    可以看到x1 = 480 / 基准 = 480 / 320 = 1.5 ;它的意思就是同样的1px,在320/480分辨率的手机上是1px,在480/800的分辨率的手机上就是1*1.5px,px会根据我们指定的不同values文件夹自动适配为合适的大小。

    • 自动生成 dimen-px 文件
      • 首先下载jar包:
        链接: http://pan.baidu.com/s/1crbwwI 密码: dxwa
      • 其次解压查看jar运行说明.txt文件,定制以1280/720为基准的分辨率,操作方法:
        在你下载后的文件夹里面 按住Shift+鼠标右击进入命令行对话框,输入
        java -jar autolayout.jar 720 1280就会自动生成res文件夹(默认的是以1080/1280为基准,所以需要自己设置),假如你觉得这些value文件夹里面没有你想要的分辨率可以在制定基准分辨率的同时,添加额外的分辨率(比如400/600),输入java -jar autolayout.jar 720 1280 400,600,假如想多添加几个额外的分辨率(又想添加500*700)只需把额外的分辨率用下划线隔开即可,输入java -jar autolayout.jar 720 1280 400,600_500,700
      • 接着把res里面的value文件夹放到res下面即可
      • 美女设计师给我们设计图(标记好了各个控制的大小距离等等),肯定是以px为标记的,那假如宽50px,高80px,我们只需要把宽高写为@dimen/x50,@dimen/y80即可

    14. 后续

    如果大家喜欢这篇文章,欢迎点赞;如果想看更多前端移动端后端Java或Python方面的技术,欢迎关注!

    相关文章

      网友评论

      • JarryLeo:推荐一个屏幕适配库:https://www.jianshu.com/p/21eadaf65207 不用写一句代码搞定适配(今日头条方案):wink:
      • 芋头先生0:UI给的设计图是720 1280 的 ,是不是直接用你的代码就好,不用改宽度了,另外用不用在application或者fragment里添加DisplayUtil.setCustomDensity(this, getApplication());
        那句话
        付凯强:1. 不用在application 初始化 在baseActivity中初始化就行。2. 你的设计图是两倍图,两倍图意味着你的px = dp * 2 所以这个时候你在写布局的时候 需要把dp写成设计图的1/2 。
      • inke:写完后,没有校对一下,例如:720360设计图大小(3602=720 两倍
        这个没看懂啥意思?
        付凯强:@inke 720 360中间的这个*号因为Md兼容性的问题导致消失了。720 指的是 720p 。也就是1280 720的大小。Android 一倍设计图是 720 360 的大小 。所以720 是 360的 两倍,1280 720 是两倍图。
      • 漫天飞雪_f643:厉害,点个赞!
      • 117eb4f82123:感觉写的有些乱,稍微再调理一下就好了。:smiley:
        付凯强:已整理,如果还是觉得乱,我会再改进。
        付凯强:好的,周末我修改一下,前一个月太忙了,多谢指正。
      • bebbeb347240:从概念上看,density应该是dpi的平方。
        付凯强:@愉悦joyful 这种说法还不太了解,我也查下。
        bebbeb347240:@剑走偏锋雨 dpi: 每英寸中的像素数;density: 每平方英寸中的像素数。
        付凯强:为什么
      • IT人故事会:老铁,写的很用心,你的文章我收藏了啊
        付凯强:@IT人故事会 识货!一起努力!

      本文标题:看了一定会有收获的屏幕适配全解析

      本文链接:https://www.haomeiwen.com/subject/qjnilftx.html