我個人覺得Android適配似乎沒有完美的方案,需要有一定的經(jīng)驗與技巧才能更好的適配各種分辨率問題,我覺得能夠適配百分之90以上的機型也就差不多了。
其實之前一直糾結谷歌谷歌推薦我們使用dp設置view的寬高,年輕時候的我一直是這么做的,后來發(fā)現(xiàn)每一步手機的寬不一定是相同dp的,大部分在300到400左右 dp 吧,所以我發(fā)現(xiàn)dp不能很好的控制view在屏幕的占用比例,現(xiàn)在谷歌出了一個關于百分比的東西似乎能很好解決這個問題,但是有局限性,這里先不講,后續(xù)有空可能會補上。
之前看過鴻洋大神的一個不錯的適配方案(慕課網(wǎng)也有同樣的適配方案),是以某個分辨率為基準,將一個屏幕的寬分成320份,高分為480份,以像素作為單位,生成多個分辨率的文件。這樣看基本是看不懂的,可以先屢一下思路:基于百分比的思想,我們可以把一個屏幕的寬分為320份,高同理,每個不同分辨率屏幕的320份所擁有的的像素點一般是不一樣的,所以需要在每種分辨率的文件下生成相應的320份,看最終生成的文件比較明了:

第一個文件是默認的,新建項目就有,其他是通過代碼生成的,代碼后面給出,點開values-480320和values-800480這兩個文件,看下里面如何切分320份的:


只看寬,第一個圖是480320的文件,寬有320個像素,所以每一份都是一個像素,第一個圖是800480的文件,每一份有1.5個像素,都是一直分到320份的。所以我們就可以用這種x1,x2,x3的方式設置view的寬,大小是百分比的方式,實際上就是用像素來控制view的大小了,與谷歌所推薦的dp相違背了,但是這樣能更好適配啊,看下寫個xml看下效果如何:

屏幕設置為全屏顯示的,寬高都是沒有設置滿,設置成x310和y470,滿的話是x320和y480,索引可以看到預覽效果都是沒有顯示滿的,這里還是沒有全屏效果,谷歌手機底部的幾個虛擬按鈕也是占用用一定像素的,所以高度的顯示效果沒有體現(xiàn)出來,可以看到全面8個機子顯示是能達到我們預期效果的,后面三部就完全沒有達到效果了,為什么呢?因為最后三個設備的分辨率并沒有生成對應的文件,所有者三個設備只能在values里面找x310和y470了,如果發(fā)現(xiàn)這里沒有設置這些值的話運行可能就會報錯。
<?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();
}
}