Android 屏幕适配

简介: Android 屏幕适配

一、概念


1.1 屏幕像素密度 PPI、DPI

PPI(Pixels Per Inch)屏幕每英寸容纳多少个像素点,DPI(Dots Per Inch)这个“点”是根据屏幕物理概念产生的一个软件概念,在不同行业有不同理解,印刷行业每英寸打印多少个墨点,鼠标移动一英寸光标移动多少像素点,在Android中被用来表示屏幕每英寸显示多少个像素点,概念上可以当作没有区别。

1.2 密度无关像素 dp

density-independent pixel,是 Android 特有的单位,只与DPI有关,保证了在不同屏幕像素密度的设备上显示相同的效果。以DPI=160为基准1dp=1px,用设备实际DPI值/160=density密度,即1dp=多少px。用屏幕宽或高的px/density=屏幕宽或高最大dp长度。

px = density * dp

density = dpi / 160

1.3 独立比例像素 sp

scale-independent pixel,是 Android 特有的单位,用于设置字体大小。


二、AndroidStudi目录说明


Android会根据手机屏幕分辨率选择对应文件夹中的资源,如果没有对应的文件夹,则从最高分辨率的文件夹依次往低处寻找,找到高分辨率的就压缩后显示,找到低分辨率的就放大显示。

mipmap只用来放桌面应用图标(Manifest中application标签配置的icon项),drawable用来存放图片资源,values用来针对不同分辨力编写对应资源文件。

 

三、屏幕适配


市面上的机型,不同分辨率*不同屏幕尺寸=无限多种DPI组合。当美工给的图以px为单位使用4.1的dimen适配、以dp为单位使用4.2的字节跳动density适配、更推荐的是smallestWidth限定符适配。

dimen宽高适配

穷举市面上所有 Android 手机的屏幕像素尺寸来实现适配,通过比例换算来为不同分辨率的屏幕分别准备一套 dimens 文件,应用在运行时再去引用和当前设备完全匹配的 dimens 文件,以此来实现屏幕适配。

缺点:缺点是容错率低,只有精准匹配分辨率才能适配,否则只能引用默认dimens文件夹,显示效果就会有很大出入。

smallestWidth限定符适配

根据屏幕最短的那个边(不考虑屏幕方向)适配,适配原理和宽高限定符方案一样,也是通过比例换算来为不同尺寸的屏幕分别准备一套 dimens 文件,应用在运行时再去引用和当前设备最匹配的 dimens 文件。

优点:容错率高,没有找到对应dimens文件会向下寻找接近的。在 320 ~ 460 dp 之间每 10 dp 就提供一套 dimens 文件就足够使用了,想要囊括更多设备的话也可以再缩短步长,基本不用担心最终效果会与设计稿偏差太多,且不会影响到三方库。

缺点:需要生成多套 dimens 文件,增大了 apk 体积。

density字节跳动密度适配

基于系统将 dp 转换为 px 的公式 px = dp * density 来实现适配,通过在运行时动态修改 density 值的大小,使得修改后计算出的屏幕宽度就等于设计稿的宽度,从而使得在不同屏幕尺寸下我们都可以直接使用设计稿给出的 dp 值,且无需准备多套 dimens 文件。

优点:可以直接使用设计稿中的 dp 值,无需准备多套 dimens 文件进行映射,因此不会增大 apk 体积,且在三种方案中 UI 还原度最高,其它两种方案都需要精准命中屏幕尺寸后才能达到此方案的还原度。

缺点:由于此方案会影响到应用全局,对于已经迭代了很久的项目来说,中途引入此方案大概率会影响到现有的适配方案;即使是新项目,又需要考虑到此方案对于三方库的影响,不能由于主项目的变动导致三方库自身界面变形。

3.1 dimen宽高适配

 

 

public class DimenUtils {
    private final static String rootPath = "C:/Users/Administrator/Desktop/layoutroot/values-{0}x{1}/"; //注意将Administrator替换为实际用户名
    private final static float dw = 300f;   //屏幕横向分为多少等份
    private final static float dh = 500f;   //屏幕纵向分为多少等份
    private final static String WTemplate = "<dimen name=\"x{0}\">{1}px</dimen>\n"; //xml中横向条目的内容:<dimen name="x1">2.4px</dimen>
    private final static String HTemplate = "<dimen name=\"y{0}\">{1}px</dimen>\n"; //xml中纵向条目的内容:<dimen name="y1">2.56px</dimen>
 
    public static void main(String[] args) {    //AndroidStudio运行失败的话选择 Run 'DimenUtils.main()' with Coverage
        //720P
        makeString(720, 1280);
//        makeString(720, 1520);
//        makeString(720, 1600);
//        makeString(720, 1650);
        //1080P
//        makeString(1080, 1920);
//        makeString(1080, 2160);
//        makeString(1080, 2220);
        makeString(1080, 2340);
//        makeString(1080, 2376);
        makeString(1080, 2400);
//        makeString(1080, 2412);
        //1.5K
//        makeString(1220, 2712);
//        makeString(1240, 2772);
//        makeString(1260, 2800);
        //2K
//        makeString(1440, 2560);
//        makeString(1440, 2960);
//        makeString(1440, 3040);
        makeString(1440, 3200);
    }
 
    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>");
        float cellw = w / dw;
        for (int i = 1; i < dw; i++) {
            sb.append(WTemplate.replace("{0}", i + "").replace("{1}",
                    change(cellw * i) + ""));
        }
        sb.append(WTemplate.replace("{0}", "300").replace("{1}", w + ""));
        sb.append("</resources>");
 
        StringBuffer sb2 = new StringBuffer();
        sb2.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
        sb2.append("<resources>");
        float cellh = h / dh;
        for (int i = 1; i < dh; i++) {
            sb2.append(HTemplate.replace("{0}", i + "").replace("{1}",
                    change(cellh * i) + ""));
        }
        sb2.append(HTemplate.replace("{0}", "500").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;
    }
}
//将生成的文件夹直接拖进 AndroidStudio 中的 res 中,使用的时候就 @dimen/ 后跟方向和份数。
<TextView
    android:layout_width="@dimen/x100"
    android:layout_height="@dimen/y250"/>

3.2 smallestWidth 限定符适配

GitHub - ladingwu/dimens_sw: Android UI适配方案

3.3 density 字节跳动密度适配

一种极低成本的Android屏幕适配方式 (qq.com)

 

(332条消息) Android - 屏幕适配_android dimen适配_Jomurphys的博客-CSDN博客


目录
相关文章
|
7月前
|
编解码 Java Android开发
Android技能树 — 屏幕适配小结,2024年最新android开发环境搭建教程
Android技能树 — 屏幕适配小结,2024年最新android开发环境搭建教程
|
7月前
|
XML 编解码 Java
Android控件之高级控件——ListView、cardView、屏幕适配
Android控件之高级控件——ListView、cardView、屏幕适配
|
编解码 Android开发
Android | 老生常谈!屏幕适配原理 & 方案总结笔记
Android | 老生常谈!屏幕适配原理 & 方案总结笔记
580 0
Android | 老生常谈!屏幕适配原理 & 方案总结笔记
|
编解码 Android开发
Android屏幕适配全攻略
Android屏幕适配全攻略
294 0
Android屏幕适配全攻略
|
XML 编解码 API
浅谈 Android 屏幕适配
几组概念 分辨率 屏幕上物理像素的总数。添加对多种屏幕的支持时, 应用不会直接使用分辨率;而只应关注通用尺寸和密度组指定的屏幕尺寸及密度。
329 0
浅谈 Android 屏幕适配
|
XML 编解码 Android开发
适配完结篇一 - 超快速的Android屏幕适配方式
由于Android碎片化严重,屏幕分辨率千奇百怪,而想要在各种分辨率的设备上显示基本一致的效果,适配成本越来越高。虽然Android官方提供了dp单位来适配,但其在各种奇怪分辨率下表现却不尽如人意,因此下面探索一种简单且低侵入的适配方式。
974 0
适配完结篇一 - 超快速的Android屏幕适配方式
|
XML 编解码 Android开发
【Android 应用开发】Android屏幕适配解析 - 详解像素,设备独立像素,归一化密度,精确密度及各种资源对应的尺寸密度分辨率适配问题(二)
【Android 应用开发】Android屏幕适配解析 - 详解像素,设备独立像素,归一化密度,精确密度及各种资源对应的尺寸密度分辨率适配问题(二)
271 0
【Android 应用开发】Android屏幕适配解析 - 详解像素,设备独立像素,归一化密度,精确密度及各种资源对应的尺寸密度分辨率适配问题(二)
|
编解码 程序员 开发工具
【Android 应用开发】Android屏幕适配解析 - 详解像素,设备独立像素,归一化密度,精确密度及各种资源对应的尺寸密度分辨率适配问题(一)
【Android 应用开发】Android屏幕适配解析 - 详解像素,设备独立像素,归一化密度,精确密度及各种资源对应的尺寸密度分辨率适配问题(一)
185 0
|
XML 编解码 Android开发
Android屏幕适配讲解与实战
Android屏幕适配讲解与实战 文章大纲 一、屏幕适配是什么 二、 重要概念讲解 三、屏幕适配实战 四、项目源码下载   一、屏幕适配是什么   Android中屏幕适配就是通过对尺寸单位、图片、文字、布局这四种类型的资源进行合理的设计和规划,在布局时合理利用各种类型的资源,让布局拥有适应能力,能在各种设备下保持良好的展现效果。
1473 0
|
Android开发 编解码 API
Android APP全方位性能调优之屏幕适配终结者
优点 1. 无侵入性 首先科普下 Android 中的一个长度单位:pt,它表示一个点,是屏幕的物理尺寸,其大小为 1 英寸的 1 / 72,也就是 72pt 等于 1 英寸(其实 Android 中还有比较少见的 in 和 mm 的长度单位)。
1273 0