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

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

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)。

320dp
0.00dp
0.43dp
0.85dp
1.28dp
1.71dp
2.13dp
2.56dp
2.99dp
3.41dp
3.84dp
...
306.77dp
307.20dp
...
320dp

同理,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))