Android适配遇到很多麻烦:
- 设计图单位px而我们需要dp
- 一般网页都提供百分比计算,手机没那么幸运,需要动动脑洞
下面将主要介绍几种解决手机屏幕适配的几种方案
一、方案一:dp(独立像素密度)
首先看这个公式:
由这公式知道:
- 手机屏幕密度(每英寸打印的像素点数dpi)标准160dip–>1dp对应1px,屏幕密度(dpi)越大1dp对应的像素px越多
- 实际,1dp大约等于1/160inch,如button宽高为160dp*160dp,那么这个button在任何分辨率的屏幕中显示的尺寸大小大约是一致的(可能不精确)大概是1inch*1inch.
但是这样并不能解决所有的适配问题
1、呈现效果仍旧会有差异,仅仅是相近而已
2、当设备的物理尺寸存在差异的时候,dp就显得无能为力了。为4.3寸屏幕准备的UI,运行在5.0寸的屏幕上,很可能在右侧和下侧存在大量的空白。而5.0寸的UI运行到4.3寸的设备上,很可能显示不下。
总结:
dp与像素无关,dp能让同一数值在不同分辩率展示出大致相同的尺寸大小,但是当设备尺寸差异较大的时候,就无能为力了(这时可以建立不同规格的资源文件解决)
编写多套数字文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- values-hdpi 480X800 -->
<dimen name="imagewidth">120dip</dimen>
</resources>
<resources>
<!-- values-hdpi-1280x800 -->
<dimen name="imagewidth">220dip</dimen>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- values-hdpi 480X320 -->
<dimen name="imagewidth">80dip</dimen>
</resources>
由此我们推出百分比,并用一键生成资源文件法创建不同规格的数字文件
方案二、百分比
手机百分比适配就是让控件都参考屏幕的百分比计算宽高。
比如我现在有个需求想让控件显示的高度为屏幕的高度的1/4,
不用百分比的话实现方式两种
- 1、代码去动态计算(很多人直接pass了,太麻烦)
- 2、利用weight(weight必须依赖Linearlayout,而且并不能适用于任何场景)
上面的需求dp这个是不能完成的我么希望这样写
利用屏幕的宽和高的比例去定义View的宽和高。
<Button
android:text="@string/hello_world"
android:layout_width="20%w"
android:layout_height="10%h"/>
很多使用百分比的情形:
- match_parent (相当于100%参考父控件)
- weight(按百分比分配空间)
- 自定义view解决(里面多数尺寸是百分比计算的)
究极解决方案
现在我们要实现根据UI给的设计图px,然后既能照抄设计图px又能应用百分比适配所有机型,
原理解释
其实我们的解决方案,就是在项目中针对你所需要适配的手机屏幕的分辨率各自建立一个文件夹。
假如UI给你的设计图单位是以480*320为规格的的px,那么我们就以480*320的分辨率为基准,把任何分辨率不同规格,都分为宽320份高480份
建立资源文件夹values-480*320,这文件里的尺寸(1px就对应x1…以此类推)
<dimen name="x1">1.0px</dimen>
<dimen name="x2">2.0px</dimen>
.
.
<dimen name="x320">320px</dimen>
其他规格按比例对应如:800*480的宽度480我们对应:
<dimen name="x1">1.5px</dimen>
<dimen name="x2">3.0px</dimen>
.
.
<dimen name="x320">480px</dimen>
有人问了这TM怎么算了,好吧看下面吧—>
x1 = 480 / 基准 = 480 / 320 = 1.5 ;就是这么算的,其他一样的哈
有人又要问了,我一个个去算,一个个去写吗,肯定不是啊,我们是万能的程序员啊,哈
下面就是模板工具使用步骤了
(1)应用jar包生成资源文件
本jar默认基准为480*320,双击jar就可生成对应的文件,如果设计图给的替他规格不要虚,
例如:基准 1280 * 800 ,额外支持尺寸:1152 * 735;4500 * 3200;
jar包地址
下载jar包并在
cmd打开jar所在目录;
F:\yb>java -jar autolayout.jar 800 1280 735,1152_3200,4500
按照下面格式:
Java -jar xx.jar width height width,height_width,height
就可生成想要的res文件把这些文件拷贝到studio对应的目录即可。
jar包的源代码
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class GenerateValueFiles {
private int baseW;
private int baseH;
private String dirStr = "./res";
private final static String WTemplate = "<dimen name=\"x{0}\">{1}px</dimen>\n";
private final static String HTemplate = "<dimen name=\"y{0}\">{1}px</dimen>\n";
/**
* {0}-HEIGHT
*/
private final static String VALUE_TEMPLATE = "values-{0}x{1}";
private static final String SUPPORT_DIMESION = "320,480;480,800;480,854;540,960;600,1024;720,1184;720,1196;720,1280;768,1024;800,1280;1080,1812;1080,1920;1440,2560;";
private String supportStr = SUPPORT_DIMESION;
public GenerateValueFiles(int baseX, int baseY, String supportStr) {
this.baseW = baseX;
this.baseH = baseY;
if (!this.supportStr.contains(baseX + "," + baseY)) {
this.supportStr += baseX + "," + baseY + ";";
}
this.supportStr += validateInput(supportStr);
System.out.println(supportStr);
File dir = new File(dirStr);
if (!dir.exists()) {
dir.mkdir();
}
System.out.println(dir.getAbsoluteFile());
}
/**
* @param supportStr
* w,h_...w,h;
* @return
*/
private String validateInput(String supportStr) {
StringBuffer sb = new StringBuffer();
String[] vals = supportStr.split("_");
int w = -1;
int h = -1;
String[] wh;
for (String val : vals) {
try {
if (val == null || val.trim().length() == 0)
continue;
wh = val.split(",");
w = Integer.parseInt(wh[0]);
h = Integer.parseInt(wh[1]);
} catch (Exception e) {
System.out.println("skip invalidate params : w,h = " + val);
continue;
}
sb.append(w + "," + h + ";");
}
return sb.toString();
}
public void generate() {
String[] vals = supportStr.split(";");
for (String val : vals) {
String[] wh = val.split(",");
generateXmlFile(Integer.parseInt(wh[0]), Integer.parseInt(wh[1]));
}
}
private void generateXmlFile(int w, int h) {
StringBuffer sbForWidth = new StringBuffer();
sbForWidth.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
sbForWidth.append("<resources>");
float cellw = w * 1.0f / baseW;
System.out.println("width : " + w + "," + baseW + "," + cellw);
for (int i = 1; i < baseW; i++) {
sbForWidth.append(WTemplate.replace("{0}", i + "").replace("{1}",
change(cellw * i) + ""));
}
sbForWidth.append(WTemplate.replace("{0}", baseW + "").replace("{1}",
w + ""));
sbForWidth.append("</resources>");
StringBuffer sbForHeight = new StringBuffer();
sbForHeight.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
sbForHeight.append("<resources>");
float cellh = h *1.0f/ baseH;
System.out.println("height : "+ h + "," + baseH + "," + cellh);
for (int i = 1; i < baseH; i++) {
sbForHeight.append(HTemplate.replace("{0}", i + "").replace("{1}",
change(cellh * i) + ""));
}
sbForHeight.append(HTemplate.replace("{0}", baseH + "").replace("{1}",
h + ""));
sbForHeight.append("</resources>");
File fileDir = new File(dirStr + File.separator
+ VALUE_TEMPLATE.replace("{0}", h + "")//
.replace("{1}", w + ""));
fileDir.mkdir();
File layxFile = new File(fileDir.getAbsolutePath(), "lay_x.xml");
File layyFile = new File(fileDir.getAbsolutePath(), "lay_y.xml");
try {
PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile));
pw.print(sbForWidth.toString());
pw.close();
pw = new PrintWriter(new FileOutputStream(layyFile));
pw.print(sbForHeight.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) {
int baseW = 320;
int baseH = 400;
String addition = "";
try {
if (args.length >= 3) {
baseW = Integer.parseInt(args[0]);
baseH = Integer.parseInt(args[1]);
addition = args[2];
} else if (args.length >= 2) {
baseW = Integer.parseInt(args[0]);
baseH = Integer.parseInt(args[1]);
} else if (args.length >= 1) {
addition = args[0];
}
} catch (NumberFormatException e) {
System.err
.println("right input params : java -jar xxx.jar width height w,h_w,h_..._w,h;");
e.printStackTrace();
System.exit(-1);
}
new GenerateValueFiles(baseW, baseH, addition).generate();
}
}