基础知识
屏幕尺寸
手机对角线的物理尺寸;英寸(inch),1英寸=2.54cm
屏幕分辨率
手机在横向、纵向上的像素点数总和;px(pixel),1px=1像素点
屏幕像素密度
每英寸的像素点数;假设设备内每英寸有160个像素,那么该设备的屏幕像素密度=160dpi
密度无关像素
dp或dip,与终端上的实际物理像素点无关。在Android中,规定以160dpi(即屏幕分辨率为320x480)为基准:1dp=1px
独立比例像素
sp或sip;推荐使用12sp、14sp、18sp、22sp作为字体设置的大小,不推荐使用奇数和小数,容易造成精度的丢失问题;小于12sp的字体会太小导致用户看不清
为什么要进行Android屏幕适配
Android系统碎片化:小米定制的MIUI、魅族定制的flyme、华为定制的EMUI等等
Android机型屏幕尺寸碎片化:5寸、5.5寸、6寸等等
Android屏幕分辨率碎片化:320x480、480x800、720x1280、1080x1920

smallestWidth 限定符屏幕适配方案
开发者先在项目中根据主流屏幕的 最小宽度 (smallestWidth) 生成一系列 values-sw<N>dp 文件夹 (含有 dimens.xml 文件),当把项目运行到设备上时,系统会根据当前设备屏幕的 最小宽度 (smallestWidth) 去匹配对应的 values-sw<N>dp 文件夹,而对应的 values-sw<N>dp 文件夹中的 dimens.xml 文字中的值,又是根据当前设备屏幕的 最小宽度 (smallestWidth) 而定制的,所以一定能适配当前设备
如果系统根据当前设备屏幕的 最小宽度 (smallestWidth) 没找到对应的 values-sw<N>dp 文件夹,则会去寻找与之 最小宽度 (smallestWidth) 相近的 values-sw<N>dp 文件夹,系统只会寻找小于或等于当前设备 最小宽度 (smallestWidth) 的 values-sw<N>dp,这就是优于 宽高限定符屏幕适配方案 的容错率,并且也可以少生成很多 values-sw<N>dp 文件夹,减轻 App 的体积
什么是 smallestWidth
系统会根据当前设备屏幕的 最小宽度 来匹配 values-sw<N>dp,为什么不是根据 宽度 来匹配,而要加上 最小 这两个字呢?
这就要说到,移动设备都是允许屏幕可以旋转的,当屏幕旋转时,屏幕的高宽就会互换,加上 最小 这两个字,是因为这个方案是不区分屏幕方向的,它只会把屏幕的高度和宽度中值最小的一方认为是 最小宽度,这个 最小宽度 是根据屏幕来定的,是固定不变的,意思是不管您怎么旋转屏幕,只要这个屏幕的高度大于宽度,那系统就只会认定宽度的值为 最小宽度,反之如果屏幕的宽度大于高度,那系统就会认定屏幕的高度的值为 最小宽度
如果想让屏幕宽度随着屏幕的旋转而做出改变该怎么办呢?可以再根据 values-w<N>dp (去掉 sw 中的 s) 生成一套资源文件
如果想区分屏幕的方向来做适配该怎么办呢?那就只有再根据 屏幕方向限定符 生成一套资源文件咯,后缀加上 -land 或 -port 即可,像这样,values-sw400dp-land (最小宽度 400 dp 横向),values-sw400dp-port (最小宽度 400 dp 纵向)
├── src/main
│ ├── res
│ ├── ├──values
│ ├── ├──values-sw320dp
│ ├── ├──values-sw360dp
│ ├── ├──values-sw400dp
│ ├── ├──values-sw411dp
│ ├── ├──values-sw480dp
│ ├── ├──...
│ ├── ├──values-sw600dp
│ ├── ├──values-sw640dp
生成资源文件脚本
package com.test;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JLabel;
public class DimenDPThread implements Runnable {
private String path = File.separator + "test" + File.separator;
//UI设计尺寸(宽)
private static int wBaseDp = 400;
private static List<DimensDP> dimensData = new ArrayList<>();
static {
dimensData.add(new DimensDP(240, wBaseDp));
dimensData.add(new DimensDP(320, wBaseDp));
dimensData.add(new DimensDP(360, wBaseDp));
dimensData.add(new DimensDP(384, wBaseDp));
dimensData.add(new DimensDP(392, wBaseDp));
dimensData.add(new DimensDP(400, wBaseDp));
dimensData.add(new DimensDP(410, wBaseDp));
dimensData.add(new DimensDP(411, wBaseDp));
dimensData.add(new DimensDP(420, wBaseDp));
dimensData.add(new DimensDP(430, wBaseDp));
dimensData.add(new DimensDP(432, wBaseDp));
dimensData.add(new DimensDP(440, wBaseDp));
dimensData.add(new DimensDP(480, wBaseDp));
dimensData.add(new DimensDP(533, wBaseDp));
dimensData.add(new DimensDP(592, wBaseDp));
//600dp以后的基本是平板适配,如果你的APP不需要适配平板,那后面的就不需要加了
dimensData.add(new DimensDP(600, wBaseDp));
dimensData.add(new DimensDP(640, wBaseDp));
dimensData.add(new DimensDP(662, wBaseDp));
dimensData.add(new DimensDP(720, wBaseDp));
dimensData.add(new DimensDP(768, wBaseDp));
dimensData.add(new DimensDP(800, wBaseDp));
dimensData.add(new DimensDP(811, wBaseDp));
}
public void setPath(String path) {
this.path = path;
}
public void setwBaseDp(int wBaseDp) {
this.wBaseDp = wBaseDp;
}
@Override
public void run() {
if ("".equals(path)) {
System.out.print("path为空");
return;
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < dimensData.size(); i++) {
DimensDP dimensDP = dimensData.get(i);
String parentName = path + "values-sw" + dimensDP.getSwDp() + "dp";
System.out.print("写入文件:"+parentName+"\n");
File file = new File(parentName);
if (!file.exists()) {
file.mkdirs();
}
/************************
* 缂栧啓dimens.xml鏂囦欢
*******************************/
File dim = new File(file, "dimens.xml");
dim.delete();
writeFile(dim, sb, dimensDP);
}
}
private void writeFile(File lay, StringBuffer sb, DimensDP dimens) {
// 鍒囧嬁浣跨敤FileWriter鍐欐暟鎹紝瀹冩槸榛樿浣跨敤ISO-8859-1 or
// gb2312锛屼笉鏄痷tf-8,骞朵笖娌℃湁setEncoding鏂规硶
BufferedWriter fw = null;
try {
fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(lay, true), "UTF-8"));
fw.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "\n");
fw.write("<resources>" + "\n");
StringBuffer sp = new StringBuffer();
for (int k = 1; k < dimens.getwBaseDp() + 1; k++) {
sb.setLength(0);
sb.append(" <dimen name=\"dpx_" + k + "\">");
float dp = ((float) dimens.getSwDp() / dimens.getwBaseDp()) * k;
sb.append(dp + "dp</dimen>" + "\n");
fw.write(sb.toString());
if (k >= 5 && k <= 50) {
sp.append(" <dimen name=\"spx_" + k + "\">");
float value = ((float) dimens.getSwDp() / dimens.getwBaseDp()) * k;
sp.append(value + "sp</dimen>" + "\n");
}
}
fw.write("\n");
fw.write(" /**********字体适配***************/" + "\n");
fw.write("\n");
fw.write(sp.toString());
fw.write("</resources>");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static class DimensDP {
private int SwDp;
private int wBaseDp;
public DimensDP(int swDp, int wBaseDp) {
super();
SwDp = swDp;
this.wBaseDp = wBaseDp;
}
private int getSwDp() {
return SwDp;
}
private int getwBaseDp() {
return wBaseDp;
}
}
public static void main(String[] args) {
new Thread(new DimenDPThread()).start();
}
}
网友评论