Android屏幕适配

前言

Android屏幕碎片化严重,适配ui是一件让人头疼的问题。想完成屏幕适配,深入了解Android UI展示机制是有必要的。

本文参考了:
- Android开发者文档-Supporting Different Screens
- Android开发者文档-Supporting Multiple Screens
- 郭霖-Android官方提供的支持不同屏幕大小的全部方法

有问题或者不好的地方欢迎评论互相探讨,你的评论是我的最大动力

需了解的概念

  • 屏幕尺寸

指屏幕对角线的物理尺寸(inch),1英寸=2.54cm

  • 屏幕分辨率

指屏幕横纵向像素点(px),例:1920x1080、2560x1440

  • 屏幕像素密度

每英寸的像素点(dpi)

  • 屏幕无关像素

指与屏幕像素点无关的表示单位(dp/dip),主要用于限定控件大小

密度类型分辨率像素密度像素密度范围换算(dp->px)
ldpi320x2401200~1201dp -> 0.75px
mdpi480x320160120~1601dp -> 1px
hpdi800x480240160~2401dp -> 1.5px
xhdpi1280x720320240~3201dp -> 2px
xxhdpi1920x1080480320~4801dp -> 3px
xxxhdpi2560x1440640480~6401dp -> 4px

- 独立比例像素

指文字的统一度量单位(sp),主要用于限定字体大小,会根据用户的字体大小首选项进行缩放

  • 比较dp-sp
<!--分析applyDimension-->
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 22, getResources().getDisplayMetrics())

public static float applyDimension(int unit, float value, DisplayMetrics metrics)
{
    switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
    }
    return 0;
}

dp->px公式:value * metrics.density
sp->px公式:value * metrics.scaledDensity

调整首选项中字体大小,density不会变化,scaledDensity跟随字号变化。因此有特殊需求的情况,不让应用字体跟随设置中字号变化,可直接调整scaledDensity的值。

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Resources.getSystem().getDisplayMetrics().scaledDensity = Resources.getSystem().getDisplayMetrics().density;
        getResources().getDisplayMetrics().scaledDensity = getResources().getDisplayMetrics().density;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Resources.getSystem().getDisplayMetrics().scaledDensity = Resources.getSystem().getDisplayMetrics().density;
        getResources().getDisplayMetrics().scaledDensity = getResources().getDisplayMetrics().density;
    }
}
  • Android资源加载流程

假设手机分辨率为1920x1080,屏幕密度为480dpi
1. 系统首先会寻找是否有480dpi(即xxhdpi)的目录,是否存在对应图片
2. 如果找到就使用该目录下的图片,如果没有就一直往更高屏幕密度的目录寻找
3. 如果更高的屏幕密度目录下存在该图片,则直接使用,如果不存在则寻找低屏幕密度的目录,直至找到

使用RelativeLayout(这个就不详细解释了)

较其他的布局,更能精确的调整view位置

使用wrap_content和match_parent(这个就不详细解释了)

确保你的布局能够自适应各种不同屏幕大小

使用.9图片

避免图片拉伸、变形

限定符

从上到下,优先级依次递减

配置限定符
MCC MNCmcc310
语言en-rUS
布局方向ldrtl ldltr
最小宽度限定符sw320dp
可获得宽度w720dp
可获得高度h720dp
屏幕尺寸large
屏幕方面long notlong
屏幕方向port land
UI模式car appliance watch
夜晚模式night notnight
屏幕像素密度mdpi nodpi
触摸屏幕类型notouch finger

* 例如values-xxhdpi-1080x1800要和values-xxhdpi配合使用,当在xxhdpi没匹配到对应分辨率的数据时,将会在xxhdpi中去匹配,不会匹配错分辨率

百分比布局

动态生成px

  1. 代码生成某一分辨率下的dp对应px值
  2. 使用分辨率限定符,创建不同分辨率下的dp数值文件

    • 注意:最好加上屏幕密度限定符一起限制会更加精准(values-xxhdpi-1080x1800)。在分辨率1080x1800下,可能适配不到values-1800x1080目录,使用以下代码检查对应分辨率及密度。
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int widthPixels = displayMetrics.widthPixels;   // 真实宽度分辨率
int heightPixels = displayMetrics.heighthPixels;   // 真实高度分辨率
int densityDPI = displayMetrics.densityDpi; // 屏幕密度
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值