android 屏幕适配

来源:互联网 发布:淘宝打不开卖家店铺 编辑:程序博客网 时间:2024/06/06 09:59

1.屏幕适配方案

  • 1.尽量使用dp

    Density-independent pixel (dp)独立像素密度。标准是160dip.即1dp对应1个pixel,计算公式如:px = dp * (dpi / 160),屏幕密度越大,1dp对应 的像素点越多。
    上面的公式中有个dpi,dpi为DPI是Dots Per Inch(每英寸所打印的点数),也就是当设备的dpi为160的时候1px=1dp
    好了,上述这些概念记不记得住没关系,只要记住一点dp是与像素无关的,在实际使用中1dp大约等于1/160inch。

    那么dp究竟解决了适配上的什么问题?可以看出1dp = 1/160inch;那么它至少能解决一个问题,就是你在布局文件写某个View的宽和高为160dp*160dp,这个View在任何分辨率的屏幕中,显示的尺寸大小是大约是一致的(可能不精确),大概是 1 inch * 1 inch。

    但是,这样并不能够解决所有的适配问题:

    呈现效果仍旧会有差异,仅仅是相近而已
    当设备的物理尺寸存在差异的时候,dp就显得无能为力了。为4.3寸屏幕准备的UI,运行在5.0寸的屏幕上,很可能在右侧和下侧存在大量的空白。而5.0寸的UI运行到4.3寸的设备上,很可能显示不下。;

    一句话,总结下,dp能够让同一数值在不同的分辨率展示出大致相同的尺寸大小。但是当设备的尺寸差异较大的时候,就无能为力了。适配的问题还需要我们自己去做

    可以看出,dp并没有能解决适配问题。下面看百分比。

  • 2.百分比
    这个概念不用说了,web中支持控件的宽度可以去参考父控件的宽度去设置百分比,最外层控件的宽度参考屏幕尺寸设置百分比,那么其实中Android设备中,只需要支持控件能够参考屏幕的百分比去计算宽高就足够了。
    比如,我现在以下几个需求:

    对于图片展示的Banner,为了起到该有的效果,我希望在任何手机上显示的高度为屏幕高度的1/4
    我的首页分上下两栏,我希望每个栏目的屏幕高度为11/24,中间间隔为1/12
    slidingmenu的宽度为屏幕宽度的80%
    当然了这仅仅是从一个大的层面上来说,其实小范围布局,可能百分比将会更加有用。

    那么现在不支持百分比,实现上述的需求,可能需要1、代码去动态计算(很多人直接pass了,太麻烦);2、利用weight(weight必须依赖Linearlayout,而且并不能适用于任何场景)

    再比如:我的某个浮动按钮的高度和宽度希望是屏幕高度的1/12,我的某个Button的宽度希望是屏幕宽度的1/3。

    上述的所有的需求,利用dp是无法完成的,我们希望控件的尺寸可以按照下列方式编写:

       <Button        android:text="@string/hello_world"        android:layout_width="20%w"        android:layout_height="10%h"/>

    利用屏幕的宽和高的比例去定义View的宽和高。

    好了,到此我们可以看到dp与百分比的区别,而百分比能够更好的解决我们的适配问题。

    some 适配tips
    我们再来看看一些适配的tips

    多用match_parent
    多用weight
    自定义view解决
    其实上述3点tip,归根结底还是利用百分比,match_parent相当于100%参考父控件;weight即按比例分配;自定义view无非是因为里面多数尺寸是按照百分比计算的;

    通过这些tips,我们更加的看出如果能在Android中引入百分比的机制,将能解决大多数的适配问题,下面我们就来看看如何能够让Android支持百分比的概念。

  • 3.百分比引入
    1、引入
    其实我们的解决方案,就是在项目中针对你所需要适配的手机屏幕的分辨率各自建立一个文件夹。
    然后我们根据一个基准,为基准的意思就是:
    比如480*320的分辨率为基准
    宽度为320,将任何分辨率的宽度分为320份,取值为x1~x320
    高度为480,将任何分辨率的高度分为480份,取值为y1~y480
    就是以后每一个屏幕尺寸都按照这个基准来平分。我们只需要按照这个基准定义的dimen就可以由android 系统去自动匹配。并且在任何设备上都是一样的。
    例如对于800*480的宽度480:可以看到x1 = 480 / 基准 = 480 / 320 = 1.5 ;

    用来生成不同屏幕下的values目录和文件来进行适配

        package com.aaron.generator;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.PrintWriter;/** * 生成Values 文件 指定文件屏幕尺寸 *  * @author pc * */public class GenerateValueFiles {    /**     * 根目录     */    private String dirStr ="res";    /**     * 基准 Width     */    private int baseW;    /**     * 基准 Height     */    private int baseH;    /**     * 支持的尺寸     */    private String supportStr = SUPPORT_DIMESION;    private static String wTemp = "<dimen name=\"x{0}\">{1}px</dimen>\n";    private static String hTemp = "<dimen name=\"y{0}\">{1}px</dimen>\n";    /**     * {0} HEIGHT     */    private static final String valueTemp = "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;";    public GenerateValueFiles(int baseX, int baseY, String support) {        this.baseW = baseX;        this.baseH = baseY;        if (!this.supportStr.contains(baseX + "," + baseY)) {            this.supportStr += baseX + "," + baseY + ";";        }        this.supportStr += validateInput(support);        System.out.println(this.supportStr);        File resDir = new File(dirStr);        if (!resDir.exists()) {            resDir.mkdirs();        }        System.out.println(resDir.getAbsolutePath());    }    /**     * supportStr w,h_w1,h1..._w9,h9;     *      * @param supportStr     * @return     */    private String validateInput(String supportStr) {        StringBuilder sb = new StringBuilder();        String[] screensValues = supportStr.split("_");        int w = -1;        int h = -1;        String[] wh;        for (String val : screensValues) {            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 invliate params " + val);                continue;            }            sb.append(w).append(",").append(h).append(";");        }        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) {        String fileName = valueTemp.replace("{0}", h + "").replace("{1}", w + "");        String wContent = generateXmlContent(w, baseW, wTemp);        String hContent = generateXmlContent(h, baseH, hTemp);        File valuesFolder = new File(dirStr + File.separator + valueTemp.replace("{0}", h + "").replace("{1}", w + ""));        if (!valuesFolder.exists())            valuesFolder.mkdirs();        File widthXmlFile = new File(valuesFolder.getAbsolutePath(), "lay_x.xml");        File heightXmlFile = new File(valuesFolder.getAbsolutePath(), "lay_y.xml");        try {            PrintWriter pw = new PrintWriter(new FileOutputStream(widthXmlFile));            pw.write(wContent);            pw.close();            PrintWriter ph = new PrintWriter(new FileOutputStream(heightXmlFile));            ph.write(hContent);            ph.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    /**     * 生成xml文本     *      * @param w     */    private String generateXmlContent(int size, int baseSize, String temp) {        StringBuilder s = new StringBuilder();        //s.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");        s.append("<resources>\n");        float cell = size * 1.0f / baseSize;        System.out.println("width : " + size + "," + baseSize + "," + cell);        for (int i = 1; i < baseSize; i++) {// 按照基准将 size平分            s.append(temp.replace("{0}", i + "").replace("{1}", change(cell * i) + "")).append("\n");        }        s.append(temp.replace("{0}", baseSize + "").replace("{1}", size + "")).append("\n");        s.append("</resources>");        return s.toString();    }    /**     * 保留两位小数     *      * @param val     * @return     */    public static float change(float val) {        int temp = (int) (val * 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 GenerateValueFiles(baseW, baseH, addition).generate();    }}

可以打包成jar包

eclipse:> File->export->general_java_runnable jar->browser选择存放目录->finish;

执行jar包

java -jar filename.jar params1 params2 params3如:java -jar generate.jar 320 480 [可写]1280,960_1231,342_...

本文完全按照【鸿洋】的文章而成,我只是想要自己动手记录一下加深记忆。如果向看原文。

http://blog.csdn.net/lmj623565791/article/details/45460089

0 0
原创粉丝点击