美文网首页
Android UI适配总结之尺寸适配(2)

Android UI适配总结之尺寸适配(2)

作者: 天空蔚蓝依旧 | 来源:发表于2019-11-09 14:28 被阅读0次

    很想和你们唠叨几句,聊聊入行后我下移的发际线是怎么做到的!奈何不善言谈,虽心有千言万语,竟只能对着屏幕叹一声下次再聊。
    本人学识有限,错误之处还望各位大佬斧正。[]( ̄▽ ̄)*下面进入正题。

    1.使用dp、sp、wrap_content、match_parent
    2.布局中使用weight或者ConstraintLayout等灵活布局
    3.通配符适配,如:layout-sw320dp、values-sw320dp
    4.头条方案

    使用1、2两种方法,也是我们开发中最常用的方法,基本能满足我们大部分(80%左右)机型的适配,但是还有小部分的机型显示会出现问题,这时候我们就要用到了3、4两种方法的一种。

    通配符

    先来说说通配符,通配符适配是Google早期为了能让APP能同时适配手机和平板而提供的功能,后被用于解决Android手机屏幕尺寸碎片化引起的适配问题。

    通配符的格式:文件名+通配符限制,中间用“-”连接。
    我们常用的分辨率适配:drawbale-1920*1080、drawbale-1280*720等
    宽度适配:values-sw320dp、values-sw360dp等

    ├── src/main
    │   ├── res
    │   ├── ├──values
    │   ├── ├──values-sw320dp
    │   ├── ├──values-sw360dp
    │   ├── ├──values-sw400dp
    │   ├── ├──values-sw411dp
    │   ├── ├──values-sw480dp
    │   ├── ├──...
    │   ├── ├──values-sw600dp
    │   ├── ├──values-sw640dp
    

    上面是我公司项目使用的通配符适配目录。是不是很熟悉?没错,这个基本是个固定的目录格式,已经有大神帮我设计好了,我们只要照搬这个目录就可以了。(你要是觉的不够精细,可以自己增加 ̄▽ ̄)既然我们用了通配符,那么values中的dimens.xml想必是不一样(*^▽^*),下面我举个例子来说明dimens中值是怎么计算出来的!
    假设UI给的设计图尺寸是1280*750,我要计算的是sw320dp-》dimens
    屏幕宽度320dp、设计图750px,
    如果要把屏幕占满我们需要设置view的宽度为320dp或者750px、
    如果占一半view的宽度为160dp或者375px、
    依次类推我们能看出dp和px之间的比例是固定的320/750=160/375....=0.43。也就是说1px=0.43dp。总体来看就是我们把320dp的屏幕分成了750份,用每份来替换dp值(如:1px(pb_px_1)=0.43dp)。

    <dimen name="base_dpi">320dp</dimen>
    <dimen name="qb_px_0">0.00dp</dimen>
    <dimen name="qb_px_1">0.43dp</dimen>
    <dimen name="qb_px_2">0.85dp</dimen>
    <dimen name="qb_px_3">1.28dp</dimen>
    <dimen name="qb_px_4">1.71dp</dimen>
    <dimen name="qb_px_5">2.13dp</dimen>
    <dimen name="qb_px_6">2.56dp</dimen>
    <dimen name="qb_px_7">2.99dp</dimen>
    <dimen name="qb_px_8">3.41dp</dimen>
    <dimen name="qb_px_9">3.84dp</dimen>
    ...
    <dimen name="qb_px_719">306.77dp</dimen>
    <dimen name="qb_px_720">307.20dp</dimen>
    ...
    <dimen name="qb_px_750">320dp</dimen>
    

    同理,sw360dp也是把屏幕分成750份、每份360/750=0.48
    Android Studio自动生成dimens插件下载
    由于Android的碎片化,会有各种稀奇古怪的手机宽度是上面没有的通配宽度,(sw -> small width 最小宽度通配符) ,遇到这种情况系统会自动帮我想下查找最近的通配宽度。
    假如有一台340dp的手机,而我们的统配符有没有340dp,那么会自动先下查找到并使用sw320dp的参数。但是我们手机的宽度明明是340dp,却用的320dp的参数,这不是产生了误差。没错,但是这种误差基本可以忽略,下面我们来简单算算。
    340/750=0.45
    320/750=0.43
    如果一个view的高度是30dp,那么两者的误差为0.6dp,0.6/30*100=2%
    一个30dp的view,误差小于1dp(2%),这点差异完全可以忽略,显示效果用眼睛看不出差异。
    所以通过增加通配符各种不同的尺寸,能让我们的UI适配更完善。但是,相应的也会增加app的体积。

    小结:
    优点:兼容性好、无性能消耗、
    缺点:侵入高
    ps:因为代码遗留问题,我公司app中的dimens中的计算错误,造成现在只能将错就错,如果修改dimens,整个app的布局参数都要改...想想就头皮发麻

    头条方案

    先来看看几个公式:

    1. 屏幕宽度(px) = 屏幕(设计图)宽度(dp)* density;
    2. density = dpi / 160;
    3. dpi =对角线长度(px)/对角线长度(英寸)

    假如我们的手机分辨率为1920*1080、5寸,则像素密度为2203/5=440dpi
    通过上面公式我们能得出:屏幕宽度 1080/(440/160)=392.7dp
    实际宽度392dp,但是我们设计图是360dp,所以实际显示效果要比UI要小。
    1080px是屏幕的宽度,不可改变,为了让宽度是360dp,我们只能统通过修改density是宽度维持在360dp。
    到这里你应该看出来我们要修改的是density指,没错头条的方案就是修改系统的density。
    代码很简单,下面贴出来。

     public void setCustomDensity(Application application, Activity activity){
            DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
            DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
           
            scaledDensity = appDisplayMetrics.scaledDensity;
            density = appDisplayMetrics.density;
            registerComponentCallbacks(new ComponentCallbacks() {
                @Override
                public void onConfigurationChanged(Configuration newConfig) {
                    if (newConfig != null && newConfig.fontScale > 0) {
                        scaledDensity = getResources().getDisplayMetrics().scaledDensity;
                    }
                }
    
                @Override
                public void onLowMemory() {
    
                }
            });
    
            float targerDensity = appDisplayMetrics.widthPixels / 360;
            float targerScaleDensity = targerDensity * (scaledDensity / density);
            int targerDpi = (int) (targerDensity * 160);
    
            appDisplayMetrics.density = targerDensity;
            appDisplayMetrics.scaledDensity = targerScaleDensity;
            appDisplayMetrics.densityDpi = targerDpi;
           
            activityDisplayMetrics.density = targerDensity;
            activityDisplayMetrics.scaledDensity = targerScaleDensity;
            activityDisplayMetrics.densityDpi = targerDpi;
        }
    

    详情看头条官方博客

    小结:
    优点:没有性能消耗、侵入低
    缺点:没什么明显的缺点

    3、4两种方案在适配效果上都相当不俗,完全能满足大部分公司的适配需求。作为开发者我们选哪个呢?嘿嘿,怎么选择看个人意愿啦,两者没有优劣之分。

    相关文章

      网友评论

          本文标题:Android UI适配总结之尺寸适配(2)

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