Android 应用屏幕适配方案:从历史方案到现代适配思路
一种极低成本的Android屏幕适配方式 - 字节方案
一、屏幕适配到底在适配什么?
很多人一提到 Android 屏幕适配,第一反应是:
不同手机分辨率不一样,怎么让页面看起来一样?
但现在这个理解已经不够了。
现代 Android 屏幕适配要处理的不只是分辨率,还包括:
所以现在的屏幕适配,本质上不是“所有设备显示完全一样”,而是:
在不同屏幕、不同密度、不同窗口形态下,让 UI 都合理、可用、舒服。
Android 官方现在也更强调应用需要适配不同的 screen size、density 和 window configuration,因为应用看到的不是设备真实屏幕,而是当前可用窗口区域。Android 官方屏幕兼容说明
二、最基础的适配:dp、sp、density
Android 最早为了解决不同分辨率和不同密度的问题,提供了两个非常核心的单位:
比如同样是 100px,在低密度屏幕上看起来可能很大,在高密度屏幕上看起来可能很小。
所以 Android 引入了 dp:
dp是与密度无关的像素单位,系统会根据屏幕 density 自动换算成真实 px。
文字使用 sp,是因为 sp 不仅会根据 density 换算,还会受到用户系统字体大小影响。
官方也明确建议:布局尺寸使用 dp,文字大小使用 sp,不要直接使用 px。官方 density 适配说明
三、图片资源适配
Android 还提供了不同 density 的图片资源目录:
以前做 Android 开发,经常需要 UI 设计师切多套图。
现在则更推荐:
图标优先使用 VectorDrawable。
简单图形使用 shape 或 vector。
大图、照片、复杂图片再提供多密度资源。
服务端图片结合图片加载框架按需压缩、裁剪、缓存。
比如 Glide、Coil、Fresco 这类图片加载框架,本身也会帮我们处理很多图片采样和内存优化问题。
四、布局适配:不要写死尺寸
屏幕适配最常见的问题,不是 density,而是布局写死。
比如:
View 体系中,比较推荐使用:
ConstraintLayoutLinearLayout + weightRecyclerViewNestedScrollViewwrap_contentmatch_parent0dp + constraintGuidelineBarrierminWidth / maxWidth
Compose 体系中,比较推荐使用:
Modifier.fillMaxWidth()Modifier.weight()BoxWithConstraintsLazyColumnLazyVerticalGridWindowSizeClassMaterial3 Adaptive
核心思想是:
页面应该有弹性,而不是按照某一台手机的设计稿绝对定位。
五、资源限定符适配
Android 原生提供了资源限定符机制,可以根据不同条件加载不同资源。
常见目录如下:
其中 sw 是 smallest width 的意思。
比如:
以前很多项目会生成大量 values-swXXXdp,比如:
这种方案能解决一部分问题,但也有明显缺点:
资源文件太多。
维护成本高。
容易和系统字体缩放冲突。
对折叠屏、多窗口适配不够自然。
本质上还是在追求“等比例缩放”。
所以现在可以用,但不建议滥用。
六、历史上的屏幕适配方案
1. 直接使用 px
早期有些项目会直接根据设计稿写 px。
这种方式最简单,但问题最大。
因为 Android 设备密度差异很大,同样的 100px 在不同设备上视觉大小完全不同。
现在基本不推荐这种写法。
2. dp + 多套 drawable
这是 Android 官方最基础、最稳定的方案。
它解决了两个问题:
这个方案到现在仍然是基础。
不管使用什么框架,dp / sp / drawable density 都是 Android 适配的底层逻辑。
3. 多套 layout
为了适配横屏、平板、大屏,Android 允许放多套布局。
比如:
这种方式适合页面结构真的不同的场景。
比如手机上是单栏:
先进入列表页。
点击后进入详情页。
而平板上可以是双栏:
左边显示列表。
右边显示详情。
这种适配不是简单放大,而是重新组织页面结构。
4. weight 和百分比布局
以前很多页面会用 LinearLayout + weight 做比例布局。
后来 Android 也出现过 PercentRelativeLayout、PercentFrameLayout 这类百分比布局。
它们的思想是:
控件宽高不写死,而是按父容器比例分配。
这种方案在简单页面里有效,但复杂页面容易变得难维护。
后来随着 ConstraintLayout 普及,百分比布局基本就不再是主流了。
5. ConstraintLayout
ConstraintLayout 是 View 体系里非常重要的适配方案。
它适合处理复杂页面,并且可以减少布局嵌套。
常见能力包括:
ConstraintLayout 的核心价值是:
用约束关系替代绝对位置,让布局可以根据屏幕变化自动调整。
6. AutoLayout 类方案
早期也有一些 AutoLayout 方案,核心思想是:
按照设计稿尺寸,把所有控件等比例缩放。
比如设计稿是 360dp 宽,当前设备是 400dp 宽,那么所有尺寸都按比例放大。
这种方案接入简单,但缺点也明显:
容易破坏 Android 原生 dp 体系。
文字缩放不自然。
大屏设备只是简单放大,没有真正利用空间。
平板、折叠屏、多窗口适配不好。
复杂页面可能出现间距、字体、图片比例异常。
所以这种方案曾经流行,但现在已经不是推荐方向。
7. 今日头条 density 适配方案
今日头条方案曾经很有名。
它的大致思路是:
动态修改应用的 density,让设计稿宽度和设备宽度建立固定换算关系。
比如设计稿宽度是 360dp,那么通过修改 density,让当前设备宽度在代码里也表现为 360dp。
这样开发者按照设计稿写尺寸,看起来就能自动适配。
这个方案的优点是:
接入成本低。
对老项目改造比较快。
视觉还原设计稿比较容易。
缺点是:
修改 density 可能影响第三方 SDK 页面。
可能影响系统字体缩放。
可能和 WebView、Dialog、Toast、PopupWindow 等产生兼容问题。
大屏设备仍然只是等比例放大。
对折叠屏、多窗口不是最优解。
所以它适合某些强设计稿还原的项目,但不应该作为现代 Android 适配的首选方案。
8. AndroidAutoSize
AndroidAutoSize 是基于类似思路封装出来的适配框架。
它的优点是使用方便,老项目接入比较快。
但本质上还是属于“按设计稿等比例适配”的路线。
如果是老项目,页面很多、历史包袱重,可以考虑用它降低改造成本。
如果是新项目,更建议优先使用官方适配方式。
七、现代 Android 的新问题:大屏、折叠屏、多窗口
以前我们说屏幕适配,主要是在说:
这个页面在不同手机上别变形。
现在不一样了。
Android 应用可能运行在:
普通手机。
大屏手机。
平板。
折叠屏。
横屏设备。
ChromeOS。
分屏窗口。
桌面自由窗口。
这时如果还只是等比例缩放,就会出现问题。
比如一个登录按钮在手机上宽度是 320dp,看起来正常。
到了平板上,如果简单放大成 700dp,就会显得非常奇怪。
所以大屏适配的核心不是“放大”,而是“重排”。
八、Window Size Class:现代推荐方案
现在官方更推荐使用 Window Size Class。
Window Size Class 不是判断设备是不是平板,而是判断当前应用窗口有多大。
这点非常重要。
因为同一个平板:
全屏时可能是 expanded。
分屏时可能是 medium。
小窗时可能是 compact。
官方也说明,Window Size Class 是根据应用当前可用窗口大小分类,而不是根据设备物理屏幕分类。Window Size Class 官方说明
可以简单理解为:
典型页面可以这样设计:
比如列表详情页:
这才是真正适合大屏、折叠屏、多窗口的适配方式。
九、全面屏、刘海屏和 Insets 适配
现在 Android 设备大多是全面屏,适配时还要考虑:
状态栏。
导航栏。
手势导航区域。
刘海区域。
挖孔区域。
瀑布屏边缘。
折叠屏铰链区域。
以前很多项目处理沉浸式状态栏,喜欢直接设置:
状态栏透明。
导航栏透明。
给根布局加 paddingTop。
手动获取 statusBarHeight。
这种方式在早期还算常见,但现在不够稳。
现代方案应该使用 WindowInsets。
官方现在推荐 edge-to-edge 设计:背景可以绘制到系统栏后面,但文本、按钮、输入框等关键内容要避开系统栏和异形区域。官方 edge-to-edge 指南
可以理解为:
十、字体缩放也属于屏幕适配
很多项目容易忽略系统字体大小。
用户可以在系统设置里把字体调大。
如果页面没有适配,会出现:
文本被截断。
按钮文字显示不全。
标题遮挡内容。
弹窗内容溢出。
列表 item 高度不够。
所以文字适配要注意:
文字使用
sp。不要过度限制单行。
重要文案允许换行。
按钮高度不要太死。
弹窗内容可以滚动。
测试系统大字体模式。
十一、现在项目应该怎么选方案?
1. 新项目
推荐方案:
使用
dp / sp。使用 ConstraintLayout 或 Compose 自适应布局。
图标使用 VectorDrawable。
图片按需提供多密度资源。
使用
sw600dp适配平板基础布局。使用 Window Size Class 做大屏、折叠屏、多窗口适配。
使用 WindowInsets 处理状态栏、导航栏、刘海屏。
不要依赖全局 density 修改方案。
2. 老项目
如果老项目页面很多,历史布局写死严重,可以分阶段处理:
新页面使用现代方案。
核心页面逐步改成 ConstraintLayout 或 Compose。
复杂大屏页面单独做
sw600dp或 Window Size Class。如果短期改不动,可以临时使用 AndroidAutoSize 类方案兜底。
不建议全局粗暴修改所有页面,容易引入兼容问题。
3. 强设计稿还原项目
比如活动页、营销页、启动页,对视觉还原要求很高,可以考虑:
使用约束布局。
使用百分比约束。
对局部页面使用等比例适配。
复杂视觉页面用 H5 或 Compose 单独处理。
不建议把全 App 都变成设计稿缩放模型。
4. 平板和折叠屏项目
重点不是缩放,而是重排。
推荐:
列表详情双栏。
左侧导航栏。
内容区域最大宽度限制。
避免按钮、输入框无限拉宽。
横屏状态下重新组织信息层级。
使用 Window Size Class,而不是简单判断设备型号。
十二、屏幕适配的核心原则
总结下来,Android 屏幕适配有几个原则:
不要直接使用
px。布局尺寸用
dp。字体大小用
sp。不要用固定尺寸堆页面。
不要指望一套设计稿适配所有设备。
小屏优先保证内容可用。
大屏优先重新组织布局。
异形屏和系统栏用 WindowInsets。
平板、折叠屏、多窗口用 Window Size Class。
第三方适配框架可以用来救老项目,但不是现代首选方案。
十三、最后总结
Android 屏幕适配经历过几个阶段:
现在最推荐的方案不是找一个万能框架,而是组合使用官方能力:
dp / sp解决密度问题,弹性布局解决伸缩问题,资源限定符解决结构差异,WindowInsets 解决全面屏和异形屏,Window Size Class 解决大屏、折叠屏、多窗口。
一句话概括:
以前的屏幕适配追求“等比例还原设计稿”,现在的屏幕适配追求“根据窗口空间重新组织界面”。
Android 应用屏幕适配方案:从历史方案到现代适配思路
https://lautung.com/archives/QpzIUpQB
评论