Android 屏幕适配方案汇总

1、基本概念

  • 屏幕尺寸:即手机屏幕对角线的长度 单位是英寸 inch。
  • 屏幕分辨率:手机屏幕的宽 高像素点数 单位是px。一般设计给的设计稿也是以这个为单位的。
  • dpi:屏幕像素密度 1英寸有多少像素。Android上会以这个来区分 mdpi hdpi xdpi 等资源文件夹。
  • dp:密度无关像素 单位 dp,Android上推荐使用的单位
  • desity:密度,表示 1dp等于多少px

mdpi、hdpi、xdpi、xxdpi用来修饰Android中的drawable文件夹及values文件夹,用来区分不同像素密度下的图片和dimen值。

那么如何区分呢?Google官方指定按照下列标准进行区分:

名称像素密度范围
mdpi 120dpi~160dpi
hdpi160dpi~240dpi
xhdpi240dpi~320dpi
xxhdpi320dpi~480dpi
xxxhdpi480dpi~640dpi

2、解决方案

2.1 布局思路

※ 尽量使用使用wrap_content、match_parent、weight

weight属性的作用是决定控件在其父布局中的显示权重,一般用于线性布局中。

layout_weight属性值越小,则对应的layout_width或layout_height的优先级就越高,一般横向布局中,决定的是layout_width的优先级;纵向布局中,决定的是layout_height的优先级。

目前有两种方法:(1) 传统使用方法 :将layout_width和layout_height设置为fill_parent,通过 layout_weight属性控制控件的显示比例,当layout_weight越小,控件显示比例就越大。但是,如果布局中控件较多且显示比例不相同时,传统使用layout_weight属性的方法将比较麻烦。(2) 0px设值法:即使layout_width="0dp" 或layout_height="0dp",再结合layout_weight属性正比例控制控件的显示,该方法有效解决了当前Android开发中碎片化问题之一。

※ 使用相对布局,禁用绝对布局

2.2 宽高限定符适配

就是建不同手机宽高像素的values文件 如:values-480×320,然后找到一个基准分辨率,其他的分辨率都根据这个基准去把宽高等分。这样好处是我们只需要适配一个分辨率即可,缺点是命中率太低,如果没有找到当前运行的手机分辨率的文件夹,就会去拿默认dimens里的值,这样UI就可能变形了。

比如以480x320为基准分辨率
宽度为320,将任何分辨率的宽度整分为320份,取值为x1到x320
高度为480,将任何分辨率的高度整分为480份,取值为y1到y480
那么对于800480的分辨率的dimens文件来说,x1=(480/320)1=1.5px x2=(480/320)*2=3px

  • 按比例计算其他分辨率下的尺寸

480 x 320为基准分辨率,在不同分辨率的文件夹下按比例缩放尺寸,例如800 x 480

<dimen name="x1">1.5px</dimen> 480/320 = 1.5
<dimen name="x2">3px</dimen> 1.5*2 = 3
...
<dimen name="x320 ">480 px</dimen> 1.5*320 = 480

 优缺点

  • 致命缺点:容错率低,必须精准命中才能适配
  • 风险点:增大包体积

2.3 smallestWidth 限定符适配方案

提示: 最小宽度值得是屏幕的两条边最小的一个,而不是指感官意义上的宽。

1、为每种需要适配的最小宽度提供一个文件夹

res
├──values
├──values-sw320dp
├──values-sw360dp
├──values-sw400dp
├──values-sw411dp
├──values-sw480dp
  • 2、选定一个基准的最小宽度

举个例子,选定为360dp为最小宽度,将宽整份为 360 份,得到以下尺寸:

<dimen name="x1">1dp</dimen>
<dimen name="x2">2dp</dimen>
...
<dimen name="dp_360 ">360dp</dimen>
  • 3、按比例计算其他最小宽度下的尺寸

360dp为最小宽度,在不同最小宽度的文件夹下按比例缩放尺寸,例如sw480dp

<dimen name="x1">1.333dp</dimen> 480/360
<dimen name="x2">2.666dp</dimen>
...
<dimen name="dp_360 ">480dp</dimen>

优缺点:

  • 风险点:增大包体积
  • 不足:不能自动支持横竖屏切换时的适配
  • 不足:sp 也需要增加一份尺寸

2.4 今日头条适配方案

  • 1、选定以宽或高维度适配(多数选择宽)
  • 2、修改 DisplayMetrics#density
  • 3、修改 DisplayMetrics#scaledDensity
  • 4、监听系统设置中字体大小修改

代码示例:

DisplayMetrics appDisplayMetrics = mainPkgContext.getResources().getDisplayMetrics();
if (sNoncompatDensity == 0) {
    sNoncompatDensity = appDisplayMetrics.density;
    sNoncompatScaledDensity = appDisplayMetrics.scaledDensity;
    // 当修改系统字体时,会回调此方法
    mainPkgContext.getApplicationContext().registerComponentCallbacks(new ComponentCallbacks() {
        @Override
        public void onConfigurationChanged(Configuration configuration) {
            if (configuration != null && configuration.fontScale > 0) {
                sNoncompatScaledDensity = mainPkgContext.getResources().getDisplayMetrics().scaledDensity;
            }
        }

        @Override
        public void onLowMemory() {
        }
    });
}

// 320是设计图的宽度dp,可以根据自己的设计稿去修改
float targetDesity = appDisplayMetrics.widthPixels / 320;
float targetScaledDensity = targetDesity * (sNoncompatScaledDensity / sNoncompatDensity);
int targetDesityDpi = (int) (160 * targetDesity);

appDisplayMetrics.density = targetDesity;
appDisplayMetrics.scaledDensity = targetScaledDensity;
appDisplayMetrics.densityDpi = targetDesityDpi;

DisplayMetrics activityDisplayMetrics = context.getResources().getDisplayMetrics();
activityDisplayMetrics.density = targetDesity;
activityDisplayMetrics.scaledDensity = targetScaledDensity;
activityDisplayMetrics.densityDpi = targetDesityDpi;

优点

侵入性极低,效果稳定

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值