一、找一种主流屏幕做一个参考,其他的机型稍微适配
我们知道UI 设计的图已经标注都是以 px 为单位设计的。
通常我们需要根据UI设计的 图来进行一个转换操作,讲px 单位转换成我们android 系统能自适配的 dp 单位。
计算方法通常是这样的:
例如
UI 设计图是在720*1080 像素上设计的。那么我们一般会找一个 主流尺寸例如5寸手机作为参考原型。
那么参考原型的像素密度就接近240dpi。
那么我们在开发的时候,就会将标注尺寸 /(240/160) = 得到我们最终开发布局上的dp
二、根据一个基准分辨率进行其他分辨率设备的单位转换 ,思想是参考web的百分比显示
我们根据一个基准分辨率将其他主流手机屏幕分辨率都计算出来对应的值。
所为的基准就是:
比如480*320的分辨率为基准
宽度为320,将任何分辨率的宽度分为320份,取值为x1-x320
高度为480,将任何分辨率的高度分为480份,取值为y1-y480
计算方法就是
例如对于800*480的宽度480:
可以看到x1 = 480 / 基准 = 480 / 320 = 1.5 ;
我们可以写一个工具生成所有需要的分辨率文件。
代码参考链接:http://blog.csdn.net/lmj623565791/article/details/45460089
另外参考链接:http://www.cocoachina.com/android/20151030/13971.html
三、横屏dip 适配。
我们怎么样能不假思索的,不加计算的就直接按照UI设计图的标注来进行布局开发呢?
答案就是采用最小宽度限定符来限定dimen 从而当应用程序提供了多个带有不同值的最小宽度限定符资源目录时,系统会使用最接近(不超出)设备最小宽度的那个资源。
这里我们先解释下什么是最小宽度限定符:
参考链接:http://blog.csdn.net/persuit/article/details/7663574
屏幕的基本尺寸,是指最短的可用屏幕区域。具体的说,设备的最小宽度是屏幕可用的宽度和高度中最短的那个(也可以把它看做是屏幕的最小可能的宽度)。这样就可以使用这个限定符来确保应用程序至少有dp的宽度可用于UI界面,而不管屏幕的当前方向。 例如,如果布局在任何时候都需要至少600dp的最小屏幕尺寸,那么就能够使用这个限定符,在res/layout-sw600dp/目录中创建布局资源。系统只会在可用屏幕的尺寸至少是600dp的时候才会使用这些资源,而不管600dp是否是被用户认知的高度或宽度。最小宽度是设备的固定屏幕尺寸特征,当屏幕的方向发生改变时,设备的最小宽度不改变。 设备的最小宽度需要考虑屏幕的装饰和系统UI的占用。例如,如果设备有一些固定的UI元素要沿着最小宽度的轴向,占用一定的屏幕空间,那么系统声明的最小宽度要比实际的屏幕尺寸要小,因为被系统占用的像素部分对用户应用程序的UI无效。因此,这个值应该是应用程序布局所需要的最小的实际尺寸(通常,这个值是布局支持的最小宽度,而不管屏幕的当前方向)。 以下是可以使用的通用屏幕尺寸的一些值: 1.320,针对以下屏幕配置的设备: 240x320ldpi(QVGA手持设备) 320x480mdpi(手持设备) 480x800hdpi(高分辨率手持设备) 2.480,针对480x800mdpi的屏幕(平板或手持设备) 3.600,针对600x1024mdip的屏幕(7英寸平板) 4.720,针对720x1280mdip的屏幕(10英寸平板) 当应用程序提供了多个带有不同值的最小宽度限定符资源目录时,系统会使用最接近(不超出)设备最小宽度的那个资源。 这个限定符被添加在API级别13中。 还要看android:requiresSmallestWidthDp属性,它声明了与你的应用程序兼容的最小的最小宽度,并且smallestScreenWidthDp配置字段会持有这个设备最小宽度的值。
假设 我们设计的UI图是640 *1136 苹果尺寸的。那么
例如 在最小屏幕尺寸W=sw320dp 情况下,满屏宽度是320dp 那么我们要想 使我们UI设计图也能使用640 某单位=320dp , 那么某单位x = 320dp/640 。
那么x640 = 320dp 满屏宽度。这样我们在代码中就可以根据设计图的标注,直接使用x1 -x640这个单位了。
由于屏幕的高度可能会超过x640,因此这里我们需要生成更多份单位,比如最多x1280。
高度也参考这个宽度单位值,就能做到基本适配了。
我们找到了目前最常用的最小屏幕宽度尺寸如下。
然后写一个工具生成对应的单位换算值。那么在使用的时候,系统就会根据设备自动去匹配对应的文件夹中的值了。
工具代码如下:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class GenerateValueDp {
private int mBaseWidth = 640;// 基准值,设计图UI 是640*1136,那么就是以640位基准。
private int destNum = 1280;// 生成多少份 基准单位值。
private String dirStr = "./res";
private final static String WTemplate = "{1}dip\n";
private String mSupportSw = "320,360,384,400,480,600,720,800";
public GenerateValueDp(int baseWidth) {
mBaseWidth = baseWidth;
File dir = new File(dirStr);
if (!dir.exists()) {
dir.mkdir();
}
System.out.println(dir.getAbsoluteFile());
}
public void generate() {
String[] vals = mSupportSw.split(",");
for (String val : vals) {
generateXmlFile(val);
}
}
public void generateXmlFile(String swValue) {
String fileName = "values-sw" + swValue + "dp";
StringBuffer sbForWidth = new StringBuffer();
sbForWidth.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
sbForWidth.append("");
// 将设备最小宽度 例如320dp 分成基准值 640 份。每份值 320/640 dp.
float cellw = Integer.parseInt(swValue) * 1.0f / mBaseWidth;
// 我们希望能有destNum份可供我们使用。
// 当宽度为基准值640份时,宽度满屏,也就是320dp,超过基准宽度640的值可供高度使用。
for (int i = 1; i <= destNum; i++) {
sbForWidth.append(WTemplate.replace("{0}", i + "").replace("{1}",
change(cellw * i) + ""));
}
sbForWidth.append("");
File fileDir = new File(dirStr + File.separator + fileName);
fileDir.mkdir();
File layFile = new File(fileDir.getAbsolutePath(), "dimen.xml");
try {
PrintWriter pw = new PrintWriter(new FileOutputStream(layFile));
pw.print(sbForWidth.toString());
pw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static float change(float a) {
int temp = (int) (a * 100);
return temp / 100f;
}
public static void main(String[] args) {
new GenerateValueDp(640).generate();
}
}