AndroidScreenAdaptation源码深度解析actualWidth/designWidth这一个公式如何实现全分辨率一致布局【免费下载链接】AndroidScreenAdaptationA light and easy-to-use Android development screen adaptation tool library(一个轻量好用的安卓开发屏幕适配工具库)项目地址: https://gitcode.com/gh_mirrors/an/AndroidScreenAdaptation AndroidScreenAdaptation 是一个轻量好用的安卓开发屏幕适配工具库让同一套布局在不同分辨率、不同 DPI 的手机上都保持一致效果。本文深入它的源码拆解actualWidth / designWidth这一个核心公式背后的完整链路配置如何读取、屏幕参数如何采集、缩放公式如何落地到每个 View以及旋转、分屏时如何实时重算。一、适配的起点一个公式两种单位整个库的灵魂只有几行代码位于 LoadViewHelper.java 的calculateValue方法中private float calculateValue(float value) { if (px.equals(unit)) { // px 模式直接按 实际屏宽/设计图宽 的比例缩放 return value * ((float) actualWidth / (float) designWidth); } else if (dp.equals(unit)) { // dp 模式先还原成设计图里的像素值再走同一比例 int dip dp2pxUtils.px2dip(actualDensity, value); value ((float) designDpi / 160) * dip; return value * ((float) actualWidth / (float) designWidth); } return 0; }一句话概括无论布局里写的是px还是dp最终都被换算成设计图坐标系下的值再乘以actualWidth / designWidth手机实际屏宽 ÷ 设计图宽度得到当前设备上的像素值。比例一致布局自然一致。dp 模式为什么多绕了一步dp在不同密度的手机上对应的px不一样直接缩放会失真。源码的处理是两步走px2dip(actualDensity, value)用当前手机密度把屏幕上的px还原回dp见 dp2pxUtils.javadesignDpi / 160 * dip按设计图对应的标准 DPI 换算回设计图里的 px之后才统一走缩放比例。这样即使unit配成dp适配逻辑也和px模式殊途同归。二、配置从哪里来Manifest 里的四个 meta-data入口是 ScreenAdapterTools.java 的init(context)。它并不让你传参而是从AndroidManifest.xml的application节点读取四个meta-datameta-data 名称含义示例值designwidth设计图宽度px1080designdpi设计图对应的标准 DPI480fontsize全局字体倍数老板嫌字小时改这里1.0unit布局单位px或dp需统一px参考示例工程的声明方式AndroidManifest.xmlmeta-data android:namedesignwidth android:value1080 / meta-data android:namedesigndpi android:value480 / meta-data android:namefontsize android:value1.0 / meta-data android:nameunit android:valuepx / 设计图宽度与 DPI 的对应关系README 中的速查表宽24032048072010801440DPI 等级LDPIMDPIHDPIXHDPIXXHDPIXXXHDPIDPI 数值120160240320480640拿到配置后init通过IProvider回调创建AbsLoadViewHelper的具体实现LoadViewHelper并以单例形式持有getInstance()供全局调用。三、actualWidth 从哪来实时采集屏幕参数AbsLoadViewHelper构造时会调用setActualParams(context)见 AbsLoadViewHelper.java而数据源是 ActualScreen.javapublic static float[] screenInfo(Context context) { DisplayMetrics displayMetrics new DisplayMetrics(); WindowManager windowManager (WindowManager) context.getSystemService(WINDOW_SERVICE); windowManager.getDefaultDisplay().getMetrics(displayMetrics); return new float[]{displayMetrics.widthPixels, displayMetrics.heightPixels, displayMetrics.density, displayMetrics.densityDpi}; }四个值分别落到actualWidth、actualHeight、actualDensity、actualDensityDpi上。注意actualWidth是实时读取的不是启动时写死的常量——这正是后面旋转、分屏适配的基础。四、公式如何作用到每个 View递归 策略模式拿到缩放公式后还需要把公式撒到视图树的每个节点上。AbsLoadViewHelper.loadView的遍历逻辑非常直接是ViewGroup先转换自己再对每个子 View 递归或转换是叶子 View交给IConversion的transform处理。默认的 SimpleConversion.java 覆盖四类属性宽高、padding、margin、字体TextView。而LoadViewHelper里每个loadXxx方法本质就是对取值统一调用setValue()private int setValue(int value) { if (value 0) return 0; // MATCH_PARENT if (value 1) return 1; // WRAP_CONTENT return (int) calculateValue(value); } 这里的0和1特判很关键-1match_parent和-2wrap_content取反后正好是0和1直接跳过缩放避免布局语义被破坏。 如果布局里用到了minWidth/maxWidth等属性只需传入自定义策略即可ScreenAdapterTools.getInstance().loadView(decorView, new CustomConversion());自定义入口在 CustomConversion.java实现IConversion接口再继承AbsLoadViewHelper扩展属性即可扩展成本很低。五、实战接入三行代码完成全局适配在 Application 中初始化参考示例工程 App.javapublic class App extends Application { Override public void onCreate() { super.onCreate(); ScreenAdapterTools.init(this); } // 旋转/分屏适配的关键 Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); ScreenAdapterTools.getInstance().reset(this); } }在每个 Activity 的setContentView之后加一行ScreenAdapterTools.getInstance().loadView(getWindow().getDecorView());Fragment、RecyclerView 等场景则对inflater.inflate返回的 view 调用loadView(view)纯代码绘制的自定义属性可用loadCustomAttrValue(px)单独换算。reset 为什么是旋转与分屏适配的关键reset(context)会重新执行setActualParams重新采集actualWidth等屏幕参数。手机旋转后屏宽变化、Android 7.0 分屏后窗口宽度变化比例随之刷新下一次loadView就用新比例换算——这就是一个公式能覆盖旋转、分屏、不同最小宽度手机的底层原因。六、核心链路小结 Manifest meta-data ── ScreenAdapterTools.init() │ designWidth / designDpi / unit ▼ ActualScreen.screenInfo() ── actualWidth / actualDensity │ ▼ loadView(decorView) ──递归遍历── 每个 View │ ▼ setValue() ── calculateValue() ── value × (actualWidth / designWidth)总结AndroidScreenAdaptation 没有修改 density也没有强制布局单位而是用一个实际屏宽 ÷ 设计图宽的比例把设计图上的每一个 px/dp 值映射到当前设备。公式简单、链路清晰、可插拔扩展——这也是它号称完全不用改变布局编写习惯的底气所在。上手只需初始化 loadView 两行源码全部集中在screenadaptation模块值得逐行读懂。【免费下载链接】AndroidScreenAdaptationA light and easy-to-use Android development screen adaptation tool library(一个轻量好用的安卓开发屏幕适配工具库)项目地址: https://gitcode.com/gh_mirrors/an/AndroidScreenAdaptation创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考