【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 中适配不同的屏幕尺寸

相关推荐
花开月满西楼31 分钟前
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
android·前端·android studio
这儿有一堆花35 分钟前
打造你的 Android 图像编辑器:深入解析 PhotoEditor 开源库
android·开源
皮皮高2 小时前
itvbox绿豆影视tvbox手机版影视APP源码分享搭建教程
android·前端·后端·开源·tv
EnzoRay2 小时前
MotionEvent
android
玲小珑2 小时前
Auto.js 入门指南(七)定时任务调度
android·前端
墨狂之逸才3 小时前
adb常用命令调试
android
YoungForYou3 小时前
Android端部署NCNN
android
移动开发者1号3 小时前
Jetpack Compose瀑布流实现方案
android·kotlin
移动开发者1号3 小时前
Android LinearLayout、FrameLayout、RelativeLayout、ConstraintLayout大混战
android·kotlin
移动开发者1号3 小时前
ListView与RecyclerView区别总结
android·kotlin