##名词解释
####px (pixels) 最为熟悉的像素,设计图以此为单位标注;
####dp或dip (device independent pixels) 设备独立像素,与设备屏幕有关,Android的UI标注以此为单位可最大限度适配不同分辨率;
####sp (scaled pixels — best for text size):类似dp, 主要处理字体的大小;
dpi (dots per inch)屏幕像素密度,描述屏幕像素集成度。
##单位换算
Android规定以160dpi为标注,此时1dp=1px,如果像素密度为320dpi,则1dp=2px,以此类推。
##像素密度分组
参考链接 http://www.cocoachina.com/android/20151030/13971.html
将切图放到对应的分组文件夹,系统会自动去适配。
##举例
假设设计图为1920px1080px的标注图,需要运行的设备为1280px720px ,dpi=160
1、首先按标注图设置各标注尺寸,放到res\values\dimens.xml文件中,此文件中默认为160dpi的尺寸,即1dp=1px,直接按标注图写标注值即可;
2、需要适配的设备尺寸换算,由于dpi不变,仍为160dpi,但分辨率变小,在原尺寸上全部乘以系数(1280/1920)/1=2/3=0.666667(末尾会附上转换的代码),将转换后的dimens.xml文件放到res\values-sw720dp文件夹下,该文件及表示最小屏幕宽度为720dp的设备会在这个文件夹找配置文件;
3、160dpi对应的像素密度分组为hdpi,需要将切图放到res\drawable-hdpi文件夹下;
4、切图和转换后的dimens.xml文件放到对应的文件夹就完成了该设备的适配。
备注:如果要适配到1920*1080px,240dpi的设备(1.5x)上,dimens.xml的换算系数为(1920/1920)/1.5=2/3=0.6667
查看设备屏幕参数:
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int dpi = displayMetrics.densityDpi;//dpi值,如160, 240
double density = displayMetrics.density;//以160dpi为基准的像素密度,如1x,1.5x,2x等
int width = displayMetrics.widthPixels;//屏幕分辨率宽度,单位px,如1920px
int height = displayMetrics.heightPixels;//屏幕分辨率高度,单位px,如1080px
Configuration cfg = getResources().getConfiguration();
int smallScreenWidth = cfg.smallestScreenWidthDp;//最小屏幕宽度,如720dp,系统就是根据该值去查找到底需要哪一个dimens.xml文件,例如720dp的设备会使用res\values-sw720dp文件夹下的dimens.xml
//如果需要测试设置读取到的值为多少,可以加类似如下打印
Log.i(TAG,"left="+Math.round(getResources().getDimension(R.dimen.margin_left)));
一般我们需要知道的信息是dpi和最小屏幕宽度,即可完成适配。
##总结:
1、res\values\dimens.xml文件中存放的是160dpi基准尺寸,根据设备的不同需要换算适配不同的尺寸,换算后放到对应的文件夹中,如res\values-sw720dp限定符为最小屏幕宽度为720dp的设备会使用此文件夹下的配置尺寸;
2、根据dpi的不同,将切图放到对应的文件夹下,如160dpi~240dpi的设备都可将切图放到res\drawable-hdpi文件夹
3、尽可能的使用match_parent, fill_parent, wrap_content来设置控件宽高,少用dp设置宽高,dp只用于设置边距,避免使用px;
##附件:
####尺寸转换代码
package pxTodp;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 这个类用于将设计图上的像素值,转换为Android里面的dp
* 用法:1、在values文件夹的dimens.xml中按设计图填写边距及位置值,单位为dp
* 2、利用此工具将dimens.xml转为为新的值,转换倍数自定义
*/
public class DimenTool {
private static final String SOURCE_FILE_NAME = "dimens.xml";//注意文件路径,是否能找到该文件,可以将该类提取到eclipse中单独运行
private static final String DES_FILE_NAME = "dimens_720.xml";
private static final double MULTIPLE = 2.0/3.0;//设计图为1920*1080转换为1280*720
public static void gen() {
File file = new File("dimens.xml");
BufferedReader reader = null;
StringBuilder sw720 = new StringBuilder();
try {
System.out.println("生成不同分辨率:");
reader = new BufferedReader(new FileReader(file));
String tempString;
int line = 1;
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null) {
if (tempString.contains("</dimen>")) {
String start = tempString.substring(0, tempString.indexOf(">") + 1);
String end = tempString.substring(tempString.lastIndexOf("<") - 2);
int num = Integer.valueOf(tempString.substring(tempString.indexOf(">") + 1, tempString.indexOf("</dimen>") - 2)).intValue();
sw720.append(start).append((int) Math.round(num * MULTIPLE)).append(end).append("\n");
} else {
sw720.append(tempString).append("\n");
}
line++;
}
reader.close();
writeFile(DES_FILE_NAME, sw720.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
public static void writeFile(String file, String text) {
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
out.println(text);
} catch (IOException e) {
e.printStackTrace();
}
out.close();
}
public static void main(String[] args) {
gen();
}
}