Android屏幕适配方案: AutoDensity&smallest-width

本文探讨Android屏幕适配,重点介绍了smallest-width适配方案和AutoDensity库的实现,包括最小宽度限定原理、百分比布局的实现、AutoDensity的接入方法,并提出了最佳实践——结合两者,仅使用一份1:1 dimens,通过AutoDensity进行适配,以应对屏幕碎片化问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

一个Android开发工程师,在其入门后遇到的第一个考验估计就是屏幕适配。按照谷歌的适配规则,使用wrap_content、match_parent、dp等,当UI工程师换一个设备验收时,提出各种问题。这时候,估计很多人一脸懵逼,难道谷歌的适配标准是错误的?其实不是,只是还不够。android屏幕碎片化问题,导致很难一次性适配所有屏幕,这就导致了百分比适配方案的刚需。因为它用最低的成本适配了尽可能多的设备。最终今日头条屏幕适配方案和最小宽度适配方案,经过考验成为最受欢迎的两种适配方案。本文在研究了smallest-width和今日头条适配方案的基础上,用kotlin实现了smallest-width的dimens生成工具,用kotlin实现了今日头条适配方案:AutoDensity。并提出,最佳实践方案:布局和代码中用一份1:1的dimens,实际用AutoDensity一行代码实现适配,这样进可攻,退可守,在开发过程中可以无缝切换,直到正式发第一个版本时,可以选择其中一个,或者仍保留两个。

一、屏幕适配的重要概念

在开始屏幕适配之前,至少对下面几个概念有个简单理解。

1.1 屏幕尺寸、屏幕分辨率、屏幕像素密度

屏幕尺寸是指屏幕的对角线物理长度,单位英寸,1英寸=2.54厘米。如4.7英寸,5.5英寸,5.8英寸…

屏幕分辨率是指屏幕x&y轴上的物理像素值,如1920*1080。

屏幕像素密度是指单位英寸上的物理像素点数,一般是指对角线上。屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。

1.2 px、dp、dip、dpi

px也就是上面说的像素;dp和dip,即密度无关像素;dpi,也就是上面说的屏幕像素密度,假如一英寸里面有160个像素,这个屏幕的像素密度就是160dpi。在Android中,规定以160dpi为基准,1dip=1px,如果密度是320dpi,则1dip=2px,以此类推。

1.3 mdpi、hdpi、xdpi、xxdpi

了解了屏幕像素密度dpi,需要了解android中的mdpi,hdpi,xdpi,xxdpi…它们描述的是dp和px的关系,用两张表来说明:

名称 像素密度范围
mdpi 120dpi~160dpi
hdpi 160dpi~240dpi
xhdpi 240dpi~320dpi
xxhdpi 320dpi~480dpi
xxxhdpi 480dpi~640dpi
屏幕密度 图标尺寸
mdpi 48x48px
hdpi 72x72px
xhdpi 96x96px
xxhdpi 144x144px
xxxhdpi 192x192px

在计算dp和px时,mdpi是基准1比1,hdpi是1比1.5,xhdpi是1比2,以此类推。所以当UI给你设计稿时,一般可能只有像素,如1080*720,这时候还需要知道比例,也就是像素密度才能转化为Android用的dp单位。一般UI设计师也不知道,是多少比例,常用的是1比2。不过现在有很多工具是直接给dp单位的,如蓝湖,这就很方便来。

1.4 values-sw[xyz]dp

最小宽度限定,这就是smallest-width运行的基础。app在运行的时候会根据屏幕的最短边,选择对应适当的values-sw[xyz]dp目录里面的dimens。

二、smallest-width适配方案

如上面所说,app在运行的时候会根据屏幕的最短边,选择对应适当的values-sw[xyz]dp目录里面的dimens。这就是smallest-width适配方案的基础,系统具体是如何实现的,这里不做分析,只要知道这个结果,然后我们可以生成一系列的dimens,放在一系列的values-sw[xyz]dp目录,这样就达到来百分比布局的效果。
使用smallest-width作为适配方案,有一定的代码侵入,也就是要在布局文件中插入如:@dimen/dp48,这样的代码,也仅此而已,没有更多代码需要写。但是生成不同的dimens文件,这里给出一个kotlin写的工具,同时这个工具还提供方法,将现有布局文件中的dp值,改为生成的dimen对应值,不过请在了解它和自身的需求后慎重使用。

  1. DimenTypes
enum class DimenTypes(val smallestWith: Int) {
   
    SW_DP_300(300),
    SW_DP_310(310),
    SW_DP_320(320),
    SW_DP_330(330),
    SW_DP_340(340),
    SW_DP_350(350),
    SW_DP_360(360),
    SW_DP_370(370),
    SW_DP_375(375),
    SW_DP_380(380),
    SW_DP_390(390),
    SW_DP_400(400),
    SW_DP_410(410),
    SW_DP_420(420),
    SW_DP_430(430),
    SW_DP_440(440),
    SW_DP_450(450),
    SW_DP_460(460)
}
  1. DimenGenerator
package com.bottle.core.arch.smallest

import com.bottle.core.utils.domToXmlFile
import com.bottle.core.utils.writeFile
import java.io.BufferedReader
import java.io.File
import java.io.FileInputStream
import java.io.InputStreamReader
import java.math.BigDecimal
import java.util.regex.Pattern
import javax.xml.parsers.DocumentBuilderFactory

/**
 * 最大值
 */
private const val MAX_VALUE = 720

/**
 * 设计稿尺寸(将自己设计师的设计稿的宽度填入)
 */
private const val DESIGN_WIDTH = 375

/**
 * 设计稿的高度  (将自己设计师的设计稿的高度填入)
 */
private const val DESIGN_HEIGHT = 667

/**
 * 执行这个方法,将会在core模块的res目录下生成一系列的values-sw的dimens.xml
 */
fun main(args: Array<String>) {
   
   <
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值