Android适配学习总结
我个人觉得Android适配似乎没有完美的方案,需要有一定的经验与技巧才能更好的适配各种分辨率问题,我觉得能够适配百分之90以上的机型也就差不多了。
其实之前一直纠结谷歌谷歌推荐我们使用dp设置view的宽高,年轻时候的我一直是这么做的,后来发现每一步手机的宽不一定是相同dp的,大部分在300到400左右 dp 吧,所以我发现dp不能很好的控制view在屏幕的占用比例,现在谷歌出了一个关于百分比的东西似乎能很好解决这个问题,但是有局限性,这里先不讲,后续有空可能会补上。
之前看过鸿洋大神的一个不错的适配方案(慕课网也有同样的适配方案),是以某个分辨率为基准,将一个屏幕的宽分成320份,高分为480份,以像素作为单位,生成多个分辨率的文件。这样看基本是看不懂的,可以先屡一下思路:基于百分比的思想,我们可以把一个屏幕的宽分为320份,高同理,每个不同分辨率屏幕的320份所拥有的的像素点一般是不一样的,所以需要在每种分辨率的文件下生成相应的320份,看最终生成的文件比较明了:
第一个文件是默认的,新建项目就有,其他是通过代码生成的,代码后面给出,点开values-480320和values-800480这两个文件,看下里面如何切分320份的:
QQ截图20170426145115.png QQ截图20170426145201.png只看宽,第一个图是480320的文件,宽有320个像素,所以每一份都是一个像素,第一个图是800480的文件,每一份有1.5个像素,都是一直分到320份的。所以我们就可以用这种x1,x2,x3的方式设置view的宽,大小是百分比的方式,实际上就是用像素来控制view的大小了,与谷歌所推荐的dp相违背了,但是这样能更好适配啊,看下写个xml看下效果如何:
QQ截图20170426145755.png屏幕设置为全屏显示的,宽高都是没有设置满,设置成x310和y470,满的话是x320和y480,索引可以看到预览效果都是没有显示满的,这里还是没有全屏效果,谷歌手机底部的几个虚拟按钮也是占用用一定像素的,所以高度的显示效果没有体现出来,可以看到全面8个机子显示是能达到我们预期效果的,后面三部就完全没有达到效果了,为什么呢?因为最后三个设备的分辨率并没有生成对应的文件,所有者三个设备只能在values里面找x310和y470了,如果发现这里没有设置这些值的话运行可能就会报错。
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="x1">1.0dp</dimen>
<dimen name="x2">2.0dp</dimen>
<dimen name="x3">3.0dp</dimen>
<dimen name="x4">4.0dp</dimen>
上面只是复制了一部分values/lay_x.xml里面的值,这里面的值就是当某个分辨率的手机找不到自己对应的文件时就会来这里找,这里的写法我写的比较特别,x1代表1dp,x320代表320dp,所以前面那张图的后三个设备就是以dp来控制view的大小的
总的来说这个适配方法还是不错的,但是要考虑到过多的分辨率,一旦没考虑到的分辨率,该机型的适配就跟其他机型显示效果不一样了。最后想问下哪位大哥如果有更好的适配方案可以共享呢?
后面给出生成各种分辨率的代码吧
public class MakeXml {
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,1280;" +
"768,1024;" +
"800,1280;" +
"1080,1812;" +
"1080,1920;" +
"1440,2560;";
private String supportStr = SUPPORT_DIMESION;
public MakeXml(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 = 480;
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 MakeXml(baseW, baseH, addition).generate();
}
}