Android 解决屏幕适配(尺寸)

声明: 本文只讲屏幕尺寸的问题,即px–VS–各种类型屏幕
先上个结果示例

<TextView 
        android:layout_height="@dimen/x540"
        android:layout_width="@dimen/x540"
        android:background="@android:color/holo_green_dark"/>

UI给出的设计图基准1920*1080,图为540px对应的各个屏幕显示效果
这里写图片描述

一、屏幕适配的问题

相信很多Android开发人员都曾经头疼过屏幕适配的问题,当UI妹妹把她的设计图和尺寸标注图拿来的时候,我们都会无奈的瞥一眼那些红红的px标注,其实对好多开发人员来说,那些乱七八糟的标注根本就没有用,只是大致看看位置,然后凭自己的感觉去布局。一边是UI妹妹的px,一边是市场上千百种手机屏幕,我们android攻城师的事情就来了–屏幕适配。

二、各种乱七八糟的单位

各种乱起八糟的单位不想说了,想必不少人都曾经在百度上搜索,关键词为“Android 手机屏幕适配”,结果balabala出来一大堆的屏幕单位的讲解,相信大家也都能明白了。简单罗列一下:dp、sp、px、in、pt、mm等等。我就不再逐个说明了,不懂得自行百度脑补。补充说一下,还有好多可以优化适配的方法,比如用weight,matchparent、ralativelayout布局等等,在此我就不多说了。

另外想说一下我们开发时用到的values文件夹。
(a)文件夹名称中各属性的含义–(各属性是按优先级先后排列出来的)
values-mcc310-en-sw320dp-w720dp-h720dp-large-long-port-car-night-ldpi-notouch-keysexposed-nokeys-navexposed-nonav-v7
b)上述例子属性的中文说明
values-mcc310(sim卡运营商)-en(语言)-sw320dp(屏幕最小宽度)-w720dp(屏幕最佳宽度)-h720dp(屏幕最佳高度)-large(屏幕尺寸)-long(屏幕长短边模式)-port(当前屏幕横竖屏显示模式)-car(dock模式)-night(白天或夜晚)-ldpi(屏幕最佳dpi)-notouch(触摸屏模类型)-keysexposed(键盘类型)-nokey(硬按键类型)-navexposed(方向键是否可用)-nonav(方向键类型)-v7(android版本)

三、设计思路

现在在度娘上看到的各种适配方案,大部分是适配屏幕的像素密度,但是对于屏幕的宽度的适配却寥寥无几。
如果我们真的想把UI妹妹的px值完美的适配到我们各种屏幕上,我们通常的一个做法是计算原设计图中的某一个px值所占的比例,然后在各个value文件里添加合适的dp值。所用的思路方法就相当于网页设计中的百分比。举个例子,UI给出的设计图基准是1920*1080,然后一个宽度是100px,那我们在w720dp文件夹中,就添加(100/1080*720)dp。根据这个方法,我们可以根据UI的设计图基准,每个values文件中都把对应的每个px值的dp值都计算出来,那我们在开发中不就可以省事多了么。
刚听过是不是有一丝的兴奋,但是是不是又发现很麻烦?1080的宽度,我们要计算1080*5次(假设我们设定5个values文件夹)。但是我们是万能的程序员,当然是写代码的啦。。。哈哈

四、代码实现

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}dp</dimen>\n";
    private final static String HTemplate = "<dimen name=\"y{0}\">{1}dp</dimen>\n";
    private final static String VALUE_TEMPLATE = "values-sw{0}dp";
    private static final String SUPPORT_DIMESION = "320;360;480;600;720;";
    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());
    }
    private String validateInput(String supportStr) {
        StringBuffer sb = new StringBuffer();
        String[] vals = supportStr.split("_");
        int w = -1;
        String[] wh;
        for (String val : vals) {
            try {
                if (val == null || val.trim().length() == 0)
                    continue;
                wh = val.split(",");
                w = Integer.parseInt(wh[0]);
            } catch (Exception e) {
                System.out.println("skip invalidate params : w,h = " + val);
                continue;
            }
            sb.append(w);
        }
        return sb.toString();
    }
    public void generate() {
        String[] vals = supportStr.split(";");
        for (String val : vals) {
            String[] wh = val.split(",");
            generateXmlFile(Integer.parseInt(wh[0]));
        }
    }

    private void generateXmlFile(int w) {
        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>");
        File fileDir = new File(dirStr + File.separator
                + VALUE_TEMPLATE//
                        .replace("{0}", w + ""));
        fileDir.mkdir();

        File layxFile = new File(fileDir.getAbsolutePath(), "dimens.xml");
        try {
            PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile));
            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) {
        int baseW = 1080;
        int baseH = 1920;
        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();
    }

}

五、另外的疑问

UI图中给出的字体也是px值,不知道这个px值是怎么算的,我们的sp又是怎么算出来的,字体能不能精确的适配呢???还请各位大神不吝赐教。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章