Android

dimens density 屏幕适配文件

2021-09-10  本文已影响0人  猿规

在编写xml的时候,直接固定一个控件的宽高,给一个固定的dp值,在不同的屏幕上显示差别很大,导致有的手机布局无法正常显示,为了更好的达到兼容适配,会在不同尺寸下面生成不同的适配文件处理。

首先古老的适配一般就是自己计算,然后生成文件,直接规定好自己需要的尺寸,然后代码去计算生成,然后复制到项目中使用,一般常用的尺寸如下。


这里有一套计算工具类,来自动计算各尺寸下的资源。

package com.example.myapplication;

import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;

public class MakeUtils {

    private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n";
    private static final String XML_RESOURCE_START = "<resources>\r\n";
    private static final String XML_RESOURCE_END = "</resources>\r\n";
    private static final String XML_DIMEN_TEMPLETE = "<dimen name=\"qb_%1$spx_%2$d\">%3$.2fdp</dimen>\r\n";

    private static final String XML_BASE_DPI = "<dimen name=\"base_dpi\">%ddp</dimen>\r\n";
    private  static final int MAX_SIZE = 720;

    private static final String XML_NAME = "dimens.xml";

    public static float px2dip(float pxValue, int sw,int designWidth) {
        float dpValue =   (pxValue/(float)designWidth) * sw;
        BigDecimal bigDecimal = new BigDecimal(dpValue);
        float dp = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
        return dp;
    }

    /**
     * 生成所有的尺寸数据
     */
    private static String createDimens(DimenTypes type, int designWidth) {
        float dpValue;
        String temp;
        StringBuilder sb = new StringBuilder();
        try {
            sb.append(XML_HEADER);
            sb.append(XML_RESOURCE_START);
            //备份生成的相关信息
            temp = String.format(XML_BASE_DPI, type.getSwWidthDp());
            sb.append(temp);
            for (int i = 0; i <= MAX_SIZE; i++) {

                dpValue = px2dip((float) i,type.getSwWidthDp(),designWidth);
                temp = String.format(XML_DIMEN_TEMPLETE,"", i, dpValue);
                sb.append(temp);
            }
            sb.append(XML_RESOURCE_END);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * 生成的目标文件夹
     */
    public static void create(int designWidth, DimenTypes type, String buildDir) {
        try {
            //生成规则
            final String folderName;
            if (type.getSwWidthDp() > 0) {
                //适配Android 3.2+
                folderName = "values-sw" + type.getSwWidthDp() + "dp";
            }else {
                return;
            }

            //生成目标目录
            File file = new File(buildDir + File.separator + folderName);
            if (!file.exists()) {
                file.mkdirs();
            }
            Log.e("===",file.getAbsolutePath());
            //生成values文件
            FileOutputStream fos = new FileOutputStream(file.getAbsolutePath() + File.separator + XML_NAME);
            fos.write(createDimens(type,designWidth).getBytes());
            fos.flush();
            fos.close();


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
package com.example.myapplication;

/**
 * created by YooJin.
 * date: 2021/2/3 13:50
 * ldpi: 120 density:1dp=0.75px 代表尺寸 240*320
 * mdpi: 160 density:1dp=1px 代表尺寸 320*480
 * hdpi: 240 density:1dp=1.5px 代表尺寸 480*800
 * xhdpi: 320 density:1dp=2px 代表尺寸720*1280
 * xxhdpi: 480 density:1dp=3px 代表尺寸1080*1920
 */
enum DimenTypes {

    DP_sw__160(160),
    DP_sw__240(240),
    DP_sw__280(280),
    DP_sw__320(320),  
    DP_sw__360(360),
    DP_sw__400(400),
    DP_sw__420(420),
    DP_sw__440(440),
    DP_sw__480(480),
    DP_sw__560(560),
    DP_sw__640(640),
    DP_sw__720(720),
    DP_sw__800(800);

    /**
     * 屏幕最小宽度
     */
    private int swWidthDp;

    DimenTypes(int swWidthDp) {

        this.swWidthDp = swWidthDp;
    }

    public int getSwWidthDp() {
        return swWidthDp;
    }

    public void setSwWidthDp(int swWidthDp) {
        this.swWidthDp = swWidthDp;
    }

}
/**
     * 设计稿尺寸,从零开始,生成的最大尺寸
     */
    private static final int DESIGN_WIDTH = 375;

    String[] permissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
    List<String> mPermissionList = new ArrayList<>();
    public void main() {
        String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator + "res";
        DimenTypes[] values = DimenTypes.values();
        for (DimenTypes value : values) {
            MakeUtils.create(DESIGN_WIDTH, value, path);
        }
    }

执行代码后,我这里是下载目录下的res文件,然后把生成的文件剪切出来。


里面都把dimens文件生成好了。


直接把文件复制到项目里就可以直接使用了,不过不太便捷。

androidstudio上面有个插件 ScreenMatch,安装后可以直接生成这些文件,并且可以动态配置,很方便。

难得我夸一次as,一般都是喷,没少吭开发者。


安装好后直接右键会有一个ScreenMatch菜单,点它。


会发现项目里已经有两个配置文件了。


一个dimens.xml文件,是例子,生成文件的基类,需要把里面的值复制到自己values下的dimens.xml文件中,如果你项目里没有这个文件,就手动创建它。

另外一个是生成的配置文件,配置一些你需要生成的尺寸,它默认会有一些尺寸,你可以把你需要没有的添加上,把不需要的过滤掉。


在次右键选择 ScreenMatch,项目里会出现配置里的尺寸xml文件了。


跟老的值对比一下,验证是否正确,同时打开sw240dp里的xml,对应里面的值。



左边的是代码生成的,右边的是插件生成的,dp1=0.64,dp2=1.28,然后我们在打开sw800dp里的xml看看。



dp1=2.13,dp2=4.27,说明两种方式都一样,有插件省去了我们的计算。

上一篇 下一篇

猜你喜欢

热点阅读