当前位置:   article > 正文

【Android】App 屏幕适配方案

【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 函数来创建对应的屏幕分辨率

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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

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

PS:
1、该方式目前在手机上测试是正常的,不同的分辨率系统会在打开应用的时候自动切换成对应的分辨率。问题出在于开发板上,部分开发板只支持默认的分辨率,应用打开后系统不会自动选择合适的分辨率
2、屏幕适配工作在项目开发初期就应该去做了,越是拖后面,屏幕的适配难度就越大。

AndroidAutoSize

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

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

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

  • 第一步:添加依赖
dependencies {
	implementation 'me.jessyan:autosize:1.2.1'
}
  • 1
  • 2
  • 3
  • 第二步:在 AndroidManifest.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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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

点击前往

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/294683
推荐阅读
相关标签