美文网首页
Android屏幕适配

Android屏幕适配

作者: 狂奔的_土豆 | 来源:发表于2020-10-14 18:01 被阅读0次

基础知识

屏幕尺寸

手机对角线的物理尺寸;英寸(inch),1英寸=2.54cm

屏幕分辨率

手机在横向、纵向上的像素点数总和;px(pixel),1px=1像素点

屏幕像素密度

每英寸的像素点数;假设设备内每英寸有160个像素,那么该设备的屏幕像素密度=160dpi

密度无关像素

dp或dip,与终端上的实际物理像素点无关。在Android中,规定以160dpi(即屏幕分辨率为320x480)为基准:1dp=1px

独立比例像素

sp或sip;推荐使用12sp、14sp、18sp、22sp作为字体设置的大小,不推荐使用奇数和小数,容易造成精度的丢失问题;小于12sp的字体会太小导致用户看不清

为什么要进行Android屏幕适配

Android系统碎片化:小米定制的MIUI、魅族定制的flyme、华为定制的EMUI等等
Android机型屏幕尺寸碎片化:5寸、5.5寸、6寸等等
Android屏幕分辨率碎片化:320x480、480x800、720x1280、1080x1920


smallestWidth 限定符屏幕适配方案

开发者先在项目中根据主流屏幕的 最小宽度 (smallestWidth) 生成一系列 values-sw<N>dp 文件夹 (含有 dimens.xml 文件),当把项目运行到设备上时,系统会根据当前设备屏幕的 最小宽度 (smallestWidth) 去匹配对应的 values-sw<N>dp 文件夹,而对应的 values-sw<N>dp 文件夹中的 dimens.xml 文字中的值,又是根据当前设备屏幕的 最小宽度 (smallestWidth) 而定制的,所以一定能适配当前设备

如果系统根据当前设备屏幕的 最小宽度 (smallestWidth) 没找到对应的 values-sw<N>dp 文件夹,则会去寻找与之 最小宽度 (smallestWidth) 相近的 values-sw<N>dp 文件夹,系统只会寻找小于或等于当前设备 最小宽度 (smallestWidth) 的 values-sw<N>dp,这就是优于 宽高限定符屏幕适配方案 的容错率,并且也可以少生成很多 values-sw<N>dp 文件夹,减轻 App 的体积

什么是 smallestWidth

系统会根据当前设备屏幕的 最小宽度 来匹配 values-sw<N>dp,为什么不是根据 宽度 来匹配,而要加上 最小 这两个字呢?

这就要说到,移动设备都是允许屏幕可以旋转的,当屏幕旋转时,屏幕的高宽就会互换,加上 最小 这两个字,是因为这个方案是不区分屏幕方向的,它只会把屏幕的高度和宽度中值最小的一方认为是 最小宽度,这个 最小宽度 是根据屏幕来定的,是固定不变的,意思是不管您怎么旋转屏幕,只要这个屏幕的高度大于宽度,那系统就只会认定宽度的值为 最小宽度,反之如果屏幕的宽度大于高度,那系统就会认定屏幕的高度的值为 最小宽度

如果想让屏幕宽度随着屏幕的旋转而做出改变该怎么办呢?可以再根据 values-w<N>dp (去掉 sw 中的 s) 生成一套资源文件

如果想区分屏幕的方向来做适配该怎么办呢?那就只有再根据 屏幕方向限定符 生成一套资源文件咯,后缀加上 -land 或 -port 即可,像这样,values-sw400dp-land (最小宽度 400 dp 横向),values-sw400dp-port (最小宽度 400 dp 纵向)

├── src/main
│   ├── res
│   ├── ├──values
│   ├── ├──values-sw320dp
│   ├── ├──values-sw360dp
│   ├── ├──values-sw400dp
│   ├── ├──values-sw411dp
│   ├── ├──values-sw480dp
│   ├── ├──...
│   ├── ├──values-sw600dp
│   ├── ├──values-sw640dp

生成资源文件脚本

package com.test;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JLabel;

public class DimenDPThread implements Runnable {

    private String path = File.separator + "test" + File.separator;
    //UI设计尺寸(宽)
    private static int wBaseDp = 400;
    private static List<DimensDP> dimensData = new ArrayList<>();

    static {
        dimensData.add(new DimensDP(240, wBaseDp));
        dimensData.add(new DimensDP(320, wBaseDp));
        dimensData.add(new DimensDP(360, wBaseDp));
        dimensData.add(new DimensDP(384, wBaseDp));
        dimensData.add(new DimensDP(392, wBaseDp));
        dimensData.add(new DimensDP(400, wBaseDp));
        dimensData.add(new DimensDP(410, wBaseDp));
        dimensData.add(new DimensDP(411, wBaseDp));
        dimensData.add(new DimensDP(420, wBaseDp));
        dimensData.add(new DimensDP(430, wBaseDp));
        dimensData.add(new DimensDP(432, wBaseDp));
        dimensData.add(new DimensDP(440, wBaseDp));
        dimensData.add(new DimensDP(480, wBaseDp));
        dimensData.add(new DimensDP(533, wBaseDp));
        dimensData.add(new DimensDP(592, wBaseDp));
         //600dp以后的基本是平板适配,如果你的APP不需要适配平板,那后面的就不需要加了
        dimensData.add(new DimensDP(600, wBaseDp));
        dimensData.add(new DimensDP(640, wBaseDp));
        dimensData.add(new DimensDP(662, wBaseDp));
        dimensData.add(new DimensDP(720, wBaseDp));
        dimensData.add(new DimensDP(768, wBaseDp));
        dimensData.add(new DimensDP(800, wBaseDp));
        dimensData.add(new DimensDP(811, wBaseDp));

    }

    public void setPath(String path) {
        this.path = path;
    }

    public void setwBaseDp(int wBaseDp) {
        this.wBaseDp = wBaseDp;
    }

    @Override
    public void run() {

        if ("".equals(path)) {
            System.out.print("path为空");
            return;
        }

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < dimensData.size(); i++) {
            
            DimensDP dimensDP = dimensData.get(i);
            String parentName = path + "values-sw" + dimensDP.getSwDp() + "dp";
            System.out.print("写入文件:"+parentName+"\n");
            File file = new File(parentName);
            if (!file.exists()) {
                file.mkdirs();
            }

            /************************
             * 缂栧啓dimens.xml鏂囦欢
             *******************************/
            File dim = new File(file, "dimens.xml");
            dim.delete();
            writeFile(dim, sb, dimensDP);

        }

    }

    private void writeFile(File lay, StringBuffer sb, DimensDP dimens) {

        // 鍒囧嬁浣跨敤FileWriter鍐欐暟鎹紝瀹冩槸榛樿浣跨敤ISO-8859-1 or
        // gb2312锛屼笉鏄痷tf-8,骞朵笖娌℃湁setEncoding鏂规硶
        BufferedWriter fw = null;
        try {
            fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(lay, true), "UTF-8"));

            fw.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "\n");
            fw.write("<resources>" + "\n");

            StringBuffer sp = new StringBuffer();
            for (int k = 1; k < dimens.getwBaseDp() + 1; k++) {
                sb.setLength(0);
                sb.append("    <dimen name=\"dpx_" + k + "\">");
                float dp = ((float) dimens.getSwDp() / dimens.getwBaseDp()) * k;
                sb.append(dp + "dp</dimen>" + "\n");
                fw.write(sb.toString());
                if (k >= 5 && k <= 50) {
                    sp.append("    <dimen name=\"spx_" + k + "\">");
                    float value = ((float) dimens.getSwDp() / dimens.getwBaseDp()) * k;
                    sp.append(value + "sp</dimen>" + "\n");
                }
            }
            fw.write("\n");
             fw.write("    /**********字体适配***************/" + "\n");
            fw.write("\n");
            fw.write(sp.toString());
            fw.write("</resources>");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static class DimensDP {
        private int SwDp;
        private int wBaseDp;

        public DimensDP(int swDp, int wBaseDp) {
            super();
            SwDp = swDp;
            this.wBaseDp = wBaseDp;
        }

        private int getSwDp() {
            return SwDp;

        }

        private int getwBaseDp() {
            return wBaseDp;

        }

    }

    public static void main(String[] args) {

        new Thread(new DimenDPThread()).start();
    }

}

相关文章

网友评论

      本文标题:Android屏幕适配

      本文链接:https://www.haomeiwen.com/subject/qybwpktx.html