├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── sing │ │ └── uiadapter │ │ └── demo │ │ ├── Main.java │ │ ├── MainActivity.java │ │ └── MySystemParams.java │ └── res │ ├── drawable │ ├── demo1.png │ ├── demo2.jpg │ ├── ic_3.png │ ├── ic_4.png │ └── ic_5.png │ ├── layout-land │ └── main_activity.xml │ ├── layout │ └── main_activity.xml │ ├── mipmap-xhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── res │ ├── values-land-120dpi-1024x600 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-120dpi-320x240 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-120dpi-400x240 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-120dpi-432x240 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-120dpi-800x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-120dpi-854x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-160dpi-1024x600 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-160dpi-1024x768 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-160dpi-1280x720 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-160dpi-1280x768 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-160dpi-1280x800 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-160dpi-480x320 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-160dpi-800x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-160dpi-854x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-213dpi-1280x800 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-240dpi-1024x600 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-240dpi-1280x720 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-240dpi-1280x768 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-240dpi-1536x1152 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-240dpi-1920x1152 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-240dpi-1920x1200 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-240dpi-640x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-240dpi-800x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-240dpi-854x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-320dpi-1280x720 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-320dpi-1280x768 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-320dpi-1280x800 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-320dpi-1920x1200 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-320dpi-2048x1536 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-320dpi-2560x1536 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-320dpi-2560x1600 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-320dpi-960x640 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-420dpi-1920x1080 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-440dpi-2252x1080 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-440dpi-2296x1036 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-440dpi-2400x1080 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-480dpi-1920x1080 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-land-560dpi-2560x1440 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-120dpi-1024x600 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-120dpi-320x240 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-120dpi-400x240 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-120dpi-432x240 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-120dpi-800x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-120dpi-854x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-160dpi-1024x600 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-160dpi-1024x768 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-160dpi-1280x720 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-160dpi-1280x768 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-160dpi-1280x800 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-160dpi-480x320 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-160dpi-800x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-160dpi-854x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-213dpi-1280x800 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-240dpi-1024x600 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-240dpi-1280x720 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-240dpi-1280x768 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-240dpi-1536x1152 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-240dpi-1920x1152 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-240dpi-1920x1200 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-240dpi-640x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-240dpi-800x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-240dpi-854x480 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-320dpi-1280x720 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-320dpi-1280x768 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-320dpi-1280x800 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-320dpi-1920x1200 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-320dpi-2048x1536 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-320dpi-2560x1536 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-320dpi-2560x1600 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-320dpi-960x640 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-420dpi-1920x1080 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-440dpi-2252x1080 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-440dpi-2296x1036 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-440dpi-2400x1080 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-480dpi-1920x1080 │ ├── dimens_x.xml │ └── dimens_y.xml │ ├── values-port-560dpi-2560x1440 │ ├── dimens_x.xml │ └── dimens_y.xml │ └── values │ ├── dimens_x.xml │ └── dimens_y.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | /.idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UIAdapter 2 | 3 | ### `转载标明出处 ` 4 | 5 | 这是一篇关于Android屏幕适配的介绍,首先声明,不建议使用px作为单位,原因大家都知道。 6 | ###图片镇楼 7 | 8 | ![](./app/src/main/res/drawable/ic_4.png "") 9 | ![](./app/src/main/res/drawable/ic_3.png "") 10 | 看到这两张图相信大家都不陌生了,没错,这就是苦逼的适配,在2012年,OpenSignalMaps发布了第一份Android碎片化报告,统计数据表明, 11 |   2012年,支持Android的设备共有3997种。 12 |   2013年,支持Android的设备共有11868种。 13 |   2014年,支持Android的设备共有18796种。 14 |   ··· 15 |   2017年...? 16 | *** 17 | 首先需要介绍一些概念: 18 |   [原文地址](http://blog.csdn.net/ttkatrina/article/details/50623043) 19 | 20 | * px(pixels)像素,屏幕上的点,不同设备显示效果相同,例如,HVGA代表320×480像素。 21 | * in(英寸)屏幕的物理尺寸, 每英寸等于2.54厘米。 22 | * pt(point)标准长度单位, 1pt=1/72英寸,用于印刷业,UI设计师会用,iOS字体单位,Android开发不涉及。 23 | * dpi(dots per inch) 打印分辨率,每英寸所能打印的点数,即打印精度; 每英寸点数,即每英寸包含像素个数。 24 | * ppi (pixels per inch)图像分辨率, 像素密度,在图像中, 每英寸所包含的像素数目。 25 | * density(屏幕密度), density和dpi的关系为 density = dpi/160。density这个概念方便理解不同dpi的倍数关系。 26 | * dp(也即dip,device independent pixels)设备独立像素,Android特有的单位,与密度无关的像素,基于屏幕密度的抽象单位,在320x480分辨率,同时每英寸160点(dpi = 160)的显示器上,1dp = 1px。 27 | * sp(scaled pixels)放大像素,与刻度无关的像素,字体单位,可以根据用户的字体大小首选项进行缩放。sp和dp一样,是android开发里特有的单位, 查看TextView的源码可知 Android 默认使用 sp 作为字号单位。 28 | 为什么要把sp和dp代替px?最简单的原因是他们不会因为ppi的变化而变化,在相同物理尺寸和不同ppi/dpi下,他们呈现的高度大小是相同。也就是说更接近物理呈现,而px则不行。 29 | 30 | 换算关系: 31 |   px = dp * (dpi / 160),原来这里的dpi是归一化后的dpi。 32 |   则dp = px / (ppi / 160) 33 |   ppi = √(长度像素数² + 宽度像素数²) / 屏幕对角线英寸数 34 |   dp*ppi/160 = px。比如1dp x 320ppi/160 = 2px。 35 | *** 36 | ### gradle: 37 | ```groovy 38 | dependencies { 39 | ... 40 | implementation 'com.github.sing1:UIAdapter:last_version' 41 | } 42 | ``` 43 | 或者使用后面的代码自己生成,然后考到项目中,或者下载library中的代码拷贝,这个库适配的机型有: 44 | 45 | 46 | 240x320 120dpi|240x400 120dpi|240x432 120dpi|320x480 160dpi|480x640 240dpi 47 | --------------|--------------|--------------|--------------|-------------- 48 | 480x800 120dpi|480x800 160dpi|480x800 240dpi|480x854 120dpi|480x854 160dpi 49 | 480x854 240dpi|640x960 320dpi|600x1024 160dpi|600x1024 240dpi|600x1024 120dpi 50 | 720x1280 160dpi|720x1280 240dpi|720x1280 320dpi|768x1280 320dpi|768x1024 160dpi 51 | 768x1280 160dpi|768x1280 240dpi|800x1280 320dpi|800x1280 160dpi|800x1280 213dpi 52 | 1080x1920 420dpi|1080x1920 480dpi|1200x1920 320dpi|1440x2560 560dpi|1152x1536 240dpi 53 | 1152x1920 240dpi|1200x1920 240dpi|1536x2048 320dpi|1536x2560 320dpi|1600x2560 320dpi 54 | 1080x2400 440dpi|1080x2252 440dpi|1080x2296 440dpi| | 55 | 56 | 这个其中包括了横屏和竖屏,下面是生成文件的代码: 57 | 58 | ```JAVA 59 | // 竖屏文件的输出路劲 60 | private final static String rootPathPort = "/Users/Sing/Desktop/res/values-port-{0}dpi-{1}x{2}/"; 61 | // 横屏文件的输出路劲 62 | private final static String rootPathLand = "/Users/Sing/Desktop/res/values-land-{0}dpi-{1}x{2}/"; 63 | // 水平方向(X)的值 64 | private final static String templateX = " {1}dp\n"; 65 | // 垂直方向(Y)的值 66 | private final static String templateY = " {1}dp\n"; 67 | // 默认模板信息,及参照尺寸,这里用的是1280x720 320dpi 68 | private static int defaultDpi = 320; 69 | private static int defaultWidth = 720; 70 | private static int defaultHeight = 1280; 71 | private static double defaultScale = 2.0; 72 | 73 | // 将double类型的数据保留两位小数 74 | public static String twoDemal(double num) { 75 | DecimalFormat dFormat = new DecimalFormat("##0.00"); 76 | String result = dFormat.format(num); 77 | return result; 78 | } 79 | 80 | // 传入宽、高、DPI生成 81 | public static void makeString(int w, int h, int dpi) { 82 | makeValue(w,h,dpi,0);// 竖屏X 83 | makeValue(w,h,dpi,1);// 竖屏Y 84 | makeValue(w,h,dpi,2);// 横屏X 85 | makeValue(w,h,dpi,3);// 横屏Y 86 | } 87 | 88 | // type 0-3 分别为 竖屏X、竖屏Y、横屏X、横屏Y 89 | private static void makeValue(int w, int h, int dpi, int type) { 90 | double scale = ((double) dpi / 160); // 缩放比例 91 | double totalWidthDp = defaultWidth / defaultScale; // 机型水平方向总共有多少个DP 92 | double totalHeightDp = defaultHeight / defaultScale; // 机型垂直方向总共有多少个DP 93 | 94 | double portWidthValue = (double) w / scale / totalWidthDp; // 竖屏情况下,参考模板水平方向(X) 每1dp对应的适配机型的值 95 | double portHeightValue = (double) h / scale / totalHeightDp;// 竖屏情况下,参考模板垂直方向(Y) 每1dp对应的适配机型的值 96 | double landWidthValue = ((double) h / w) * portWidthValue;// 横屏情况下,参考模板水平方向(X) 每1dp对应的适配机型的值 97 | double landHeightValue = ((double) w / h) * portHeightValue;// 横屏情况下,参考模板垂直方向(Y) 每1dp对应的适配机型的值 98 | 99 | String rootPath = "";// 实际输出的路径 100 | File layFile = null; 101 | String fileName = ""; 102 | 103 | StringBuffer sb = new StringBuffer(); 104 | sb.append("\n");// 文件头 105 | sb.append("\n");// 文件头 106 | 107 | if (type == 0) { // 竖屏 X 108 | for (int i = 1; i <= 200; i++) { 109 | sb.append(templateX.replace("{0}", i + "").replace("{1}", twoDemal(portWidthValue * i) + "")); 110 | } 111 | rootPath = rootPathPort; 112 | fileName = "dimens_x.xml"; 113 | } else if (type == 1) {// 竖屏 Y 114 | for (int i = 1; i <= 200; i++) { 115 | sb.append(templateY.replace("{0}", i + "").replace("{1}", twoDemal(portHeightValue * i) + "")); 116 | } 117 | rootPath = rootPathPort; 118 | fileName = "dimens_y.xml"; 119 | } else if (type == 2) {// 横屏 X 120 | for (int i = 1; i <= 200; i++) { 121 | sb.append(templateX.replace("{0}", i + "").replace("{1}", twoDemal(landWidthValue * i) + "")); 122 | } 123 | fileName = "dimens_x.xml"; 124 | rootPath = rootPathLand; 125 | } else if (type == 3) {// 横屏 Y 126 | for (int i = 1; i <= 200; i++) { 127 | sb.append(templateY.replace("{0}", i + "").replace("{1}", twoDemal(landHeightValue * i) + "")); 128 | } 129 | rootPath = rootPathLand; 130 | fileName = "dimens_y.xml"; 131 | } 132 | sb.append("");// 文件尾 133 | 134 | String path = rootPath.replace("{0}", dpi + "").replace("{1}", h + "").replace("{2}", w + ""); 135 | File rootFile = new File(path); 136 | if (!rootFile.exists()) { 137 | rootFile.mkdirs(); 138 | } 139 | layFile = new File(path + fileName); 140 | try { 141 | PrintWriter pw = new PrintWriter(new FileOutputStream(layFile)); 142 | pw.print(sb.toString()); 143 | pw.close(); 144 | } catch (FileNotFoundException e) { 145 | e.printStackTrace(); 146 | } 147 | } 148 | 149 | // 入口在这里,想生成什么机型就传入什么机型的信息, 150 | public static void main(String[] args) { 151 | makeString(720, 1280, 320); 152 | makeString(1080, 1920, 480); 153 | // 这里可以输出你想要适配的机型 154 | } 155 | ``` 156 | 传入相应的机型后输出效果图如下: 157 | 158 | ![](./app/src/main/res/drawable/ic_5.png "") 159 | 160 | 使用生成的代码进行适配: 161 | 162 | ![](./app/src/main/res/drawable/demo1.png "") 163 | ![](./app/src/main/res/drawable/demo2.jpg "") 164 | 165 | 从图中可以看出,在1280x720和1920x1080的手机上,不管是横屏还是竖屏,控件的宽度和高度分别占据屏幕的1/2和1/4的的大小,由此说明,生成的文件计算的还是准确的,但是竖屏是个接近正方形的在横屏上却变成了长方形,是哪里出问题了? 166 | 167 | ```xml 168 | 169 | 173 | 174 |