开启成长之旅!这是我参与「日新方案 12 月更文应战」的第14天,点击检查活动详情

Android 提供了 dp 单位来做适配,那咱们为什么还要进行屏幕适配呢?咱们先来看一张图

Android 屏幕适配方案

举个例子,假如一个屏幕的分辨率是 1080 x 1920,屏幕巨细是 5 寸,那密度是多少呢?

Android 屏幕适配方案

px 和 dp 的换算公式为:px = dp * ( dpi / 160 )

咱们的 dp 单位解决了什么问题呢?

由上可知,相同的尺度,不同分辨率的设备,每 1dp 所代表的像素是不一样的。比方在 160dpi 上,1dp = 1px,在 320dpi 上,1dp = 2px,所以,dp 单位的意义在于相同尺度不同分辨率的设备上看到的巨细一样,各设备的显现份额也就一致了。

咱们的 dp 单位没有解决什么问题呢?

举个例子,一个屏幕的分辨率是 1080 x 1920,屏幕巨细是 5 寸,那么密度便是 440dpi,假设 UI 设计图是依照屏幕宽度为 360dp 来设计的,而咱们的设备宽度为 1080 / ( 440 / 160 ) = 392.7dp,也便是说,实践的屏幕宽度要比设计图宽,在这种情况下,运用 dp 也无法确保在不同设备上显现相同的作用,要是有些设备屏幕宽度不足 360dp 又依照这个设计图去开发的话,就有可能呈现显现不全的问题。并且上述的屏幕尺度,分辨率和像素密度的关系,有些设备并没有按此规矩来完结,这就导致 dpi 的值较乱,这样 dp 单位的适配作用就差强人意了。

SmallestWidth 适配

这是依据最小宽度限定符,指的是 Android 会辨认屏幕宽度最小尺度的 dp 值,然后根据辨认到的结果去寻觅对应限定符的文件夹下的资源文件,这个可以运用 Android Studio 里的 SmallestWidth Dimens 插件来完结。需求留意的是,假如没有 values-sw360dp 文件夹,体系会向下寻觅,比方离 360dp 最近的只有 values-sw340dp,那么体系就会选择 values-sw340dp 文件夹下的资源文件。

Android 屏幕适配方案

装置完结后可以在 Tools 看到 SmallestWidth,点击它会呈现如下界面

Android 屏幕适配方案

点击 Generate 会主动生成这些

Android 屏幕适配方案

基于 px 的宽高限定符适配

这种方法特别合适特定分辨率的屏幕适配,比方说,这些 Android 设备的屏幕分辨率品种不多,那就比较合适了。假如针对手机屏幕的话,那明显不合适,毕竟不同分辨率的手机实在太多了。并且,需求留意的是,这种方法,需求精准命中资源文件才干适配,比方 1920×1080 的屏幕就一定要找到 1920×1080 的限定符,否则就只能用一致的默许 dimens 文件了。

Android 屏幕适配方案

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="px_1">1px</dimen>
    <dimen name="px_2">2px</dimen>
    <dimen name="px_3">30px</dimen>
</resources>

今日头条的屏幕适配方案

基本运用

settings.gradle

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}

build.gradle

implementation 'com.github.JessYanCoding:AndroidAutoSize:v1.2.1'

在 AndroidManifest 中填写设计图尺度,单位是 dp

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.My_study"
        tools:targetApi="31">
        ...
        <meta-data
            android:name="design_width_in_dp"
            android:value="360" />
        <meta-data
            android:name="design_height_in_dp"
            android:value="640" />
    </application>
</manifest>

装备完结,是的,便是这么简略。这样,结构就可以对项目中的一切页面进行适配,不过,需求留意的是,在咱们开发阶段,布局的实时预览很重要,Android Studio 默许的预览可能不能完全符合咱们的设计图,这就需求咱们创建模拟设备了。

Android 屏幕适配方案

Android 屏幕适配方案

Android 屏幕适配方案

原理解析

dp 转化的场景,基本上都是经过 DisplayMetrics 来核算的,所以,想要满意适配,咱们只需修改 DisplayMetrics 中和 dp 转化相关的变量即可。density,scaledDensity 和 densityDpi 都可以经过 displayMetrics 获得,如下所示

val density = resources.displayMetrics.density
val densityDpi = resources.displayMetrics.densityDpi
//字体缩放因子,正常情况下等于 density,调理体系字体巨细后会改动这个值
val scaledDensity = resources.displayMetrics.scaledDensity

dp 和 px 的转化公式:px = dp * density

假如设计图宽为 360dp,想要确保在一切设备核算得出的 px 值都正好是屏幕宽度的话,咱们只能修改 density 的值。以宽为维度来适配,那么适配后的 density 就应该是:

density = 设备真实宽(px)/ 设计图宽度(dp)