##名词解释
####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,以此类推。

##像素密度分组

DPI 计算android android dpi适配_Android

DPI 计算android android dpi适配_DPI 计算android_02


参考链接 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();
    }
}