【Android】App 屏幕适配方案

自 Android 智能手机于2008年10月发布至今,已有十几年的历史,在这十几年里,Android 版本不断发生变化,搭载 Android 系统的设备也在不断的发生变化,屏幕的分辨率也从一开始的 320x480 分辨率到 1440x2560 分辨率。

Android 官方似乎一开始就意识到 app 的适配问题,推出了多达六种的像素单位,不同的单位针对不同的使用场景,分别是:dppxspptmmin

  • dp :用于布局尺寸。
  • px :表示屏幕上的实际像素数目。
  • sp :用于文本大小。
  • pt :用于印刷和排版。
  • mm :用于确保在屏幕上的物理尺寸一致。
  • in :用于确保物理尺寸一致。

虽然推出了 '如此之多' 的像素单位,但并不能根治屏幕适配的问题,于是,第一种适配方案应运而生。

系统自适应

系统自适应,是什么意思呢?

其实就是,准备好多个屏幕的尺寸,应用在安装的时候根据设备屏幕的密度自动选择合适的资源文件。

它的原理与 drawablemipmap 文件的原理相同,都是安装应用后,Android 系统会根据设备屏幕的密度自动选择合适的资源文件。这也就是为什么优化安装包大小时,部分博主会给出尽量只使用 mipmap-xhdpi 的原因之一,图片资源是真的占用 App 大小。

通过系统自适应的方式实现系统自适应屏幕大小,需要运行一套 Java 代码,运行 Java 代码的 main 函数来创建对应的屏幕分辨率。

java 复制代码
public class MakeXml {
    // 生成地址 C 盘layoutroot目录下,这个路径可以更改
    private final static String rootPath = "C:\\layoutroot\\values-{0}x{1}\\";
    /**
     * 设置基准分辨率
     * 一般标注按照多大的图标,这里我们就设置多大尺寸,单位:px
     */
    private final static float dw = 1080f;
    private final static float dh = 1920f;
    private final static String WTemplate = "<dimen name=\"x{0}\">{1}px</dimen>\n";
    private final static String HTemplate = "<dimen name=\"y{0}\">{1}px</dimen>\n";
	private final static String INDENTATION_TAG1 = "    "; 
    // 手机分辨率
    public static void main(String [] args){
        makeString(320, 480);
        makeString(480, 800);
        makeString(480, 854);
        makeString(540, 960);
        makeString(600, 1024);
        makeString(720, 1184);
        makeString(720, 1196);
        makeString(720, 1280);
        makeString(768, 1024);
        makeString(800, 1280);
        makeString(1080, 1812);
        makeString(1080, 1920);
        makeString(1440, 2560);
    }

    public static void makeString(int w, int h) {
        StringBuffer sb = new StringBuffer();
        sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
        sb.append("<resources>\n");
        float cellw = w / dw;
        for (int i = 0; i < dw; i++) {
			sb.append(INDENTATION_TAG1);
            sb.append(WTemplate.replace("{0}", i + "").replace("{1}", change(cellw * i) + ""));
        }
        //此处可将1080换为自己的基准尺寸宽度
		sb.append(INDENTATION_TAG1);
        sb.append(WTemplate.replace("{0}", "1080").replace("{1}", w + ""));
        sb.append("</resources>");
        StringBuffer sb2 = new StringBuffer();
        sb2.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
        sb2.append("<resources>\n");
        float cellh = h / dh;
        for (int i = 0; i < dh; i++) {
			sb2.append(INDENTATION_TAG1);
            sb2.append(HTemplate.replace("{0}", i + "").replace("{1}", change(cellh * i) + ""));
        }
        //此处可将1920换为自己的基准尺寸高度
		sb2.append(INDENTATION_TAG1);
        sb2.append(HTemplate.replace("{0}", "1920").replace("{1}", h + ""));
        sb2.append("</resources>");
        String path = rootPath.replace("{0}", h + "").replace("{1}", w + "");
        File rootFile = new File(path);
        if (!rootFile.exists()) {
            rootFile.mkdirs();
        }
        File layxFile = new File(path + "lay_x.xml");
        File layyFile = new File(path + "lay_y.xml");
        try {
            PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile));
            pw.print(sb.toString());
            pw.close();
            pw = new PrintWriter(new FileOutputStream(layyFile));
            pw.print(sb2.toString());
            pw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static float change(float a) {
        int temp = (int) (a * 100);
        return temp / 100f;
    }
}

执行成功后会在指定的地址生成各种屏幕分辨率的目录,根据自己设计图的尺寸,添加相对应的尺寸的 dimen 值放至 res/values/dimen.xml ,作为基本的设计尺寸。然后再其它的文件拷贝至项目的 res 目录下,使用 xml 编写 UI 时,组件的宽度从 dimen 中选择,接着运行项目,即可完成适配。

PS:

1、该方式目前在手机上测试是正常的,不同的分辨率系统会在打开应用的时候自动切换成对应的分辨率。问题出在于开发板上,部分开发板只支持默认的分辨率,应用打开后系统不会自动选择合适的分辨率

2、屏幕适配工作在项目开发初期就应该去做了,越是拖后面,屏幕的适配难度就越大。

AndroidAutoSize

如果 系统自适应 的适配方式不起效果,可以使用 AndroidAutoSize 框架去实现屏幕适配。

AndroidAutoSize 和 系统自适应 的方式实现的原理各不相同,因此 系统自适应 实现不了适配的时候可以使用 AndroidAutoSize 去做,虽然也会有点坑,但完全可以通过 AndroidAutoSizeissues 给出的方式去处理问题。

AndroidAutoSize 的使用出奇的简单,只需要两个步骤即可实现适配:

  • 第一步:添加依赖
groovy 复制代码
dependencies {
	implementation 'me.jessyan:autosize:1.2.1'
}
  • 第二步:在 AndroidManifest.xml 文件添加屏幕尺寸
xml 复制代码
<manifest>
    <application>
    	<!-- 设计稿大小,根据项目自行设置 -->
    	<meta-data
            android:name="design_width_in_dp"
            android:value="360" />
        <meta-data
            android:name="design_height_in_dp"
            android:value="640" />
    </application>
</manifest>

这样就完成了 AndroidAutoSize 对屏幕的适配工作。

点击前往 👉 AndroidAutoSize

AndroidAutoSize 存在的问题

1、无法适配 Dialog ,需要自己手动去设置、自定义的方式去调整 Dialog 的大小。

2、横屏应用部分情况会适配失败,AndroidAutoSize 出现的问题可查看 Githubissues,作者已在 issues 公布了部分问题出现的原因与处理方法。

Compose

详情请看 👉Jetpack Compose 中适配不同的屏幕尺寸

相关推荐
Dnelic-1 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记
Eastsea.Chen4 小时前
MTK Android12 user版本MtkLogger
android·framework
长亭外的少年11 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
JIAY_WX11 小时前
kotlin
开发语言·kotlin
建群新人小猿13 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神15 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛15 小时前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee
Y多了个想法15 小时前
RK3568 android11 适配敦泰触摸屏 FocalTech-ft5526
android·rk3568·触摸屏·tp·敦泰·focaltech·ft5526
NotesChapter16 小时前
Android吸顶效果,并有着ViewPager左右切换
android
_祝你今天愉快18 小时前
分析android :The binary version of its metadata is 1.8.0, expected version is 1.5.
android