在编写xml的时候,我们直接指定一个固定一个控件的宽高,给一个固定的dp值,在不同的屏幕上显示差别很大,导致有的手机布局无法正常显示,所以需要适配屏幕,这里讲的适配方式都一样,不过方法不一样

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

 

执行代码会根据定义的尺寸生成出对应的 dimens.xml 类,下面是代码

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();
        }
    }

}
View Code
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;
    }

}
View Code
package com.example.myapplication;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.widget.TextView;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

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

    String[] permissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
    List<String> mPermissionList = new ArrayList<>();

    private static final int PERMISSION_REQUEST = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        checkPermission();
        String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator + "res";
        TextView tvTag = findViewById(R.id.tv_tag);
        tvTag.setText(path);
        DimenTypes[] values = DimenTypes.values();
        for (DimenTypes value : values) {
            MakeUtils.create(DESIGN_WIDTH, value, path);
        }
    }

    private void checkPermission() {
        mPermissionList.clear();

        //判断哪些权限未授予
        for (int i = 0; i < permissions.length; i++) {
            if (ContextCompat.checkSelfPermission(this, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
                mPermissionList.add(permissions[i]);
            }
        }
        /**
         * 判断是否为空
         */
        if (mPermissionList.isEmpty()) {//未授予的权限为空,表示都授予了

        } else {//请求权限方法
            String[] permissions = mPermissionList.toArray(new String[mPermissionList.size()]);//将List转为数组
            ActivityCompat.requestPermissions(MainActivity.this, permissions, PERMISSION_REQUEST);
        }
    }

    /**
     * 响应授权
     * 这里不管用户是否拒绝,都进入首页,不再重复申请权限
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case PERMISSION_REQUEST:

                break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                break;
        }
    }

}
View Code

执行代码后打印出路径,我这里是下载目录下的res文件,注意需要先申请权限,然后把生成的文件剪切出来

里面都把dimens文件生成好了

 

直接把文件复制到项目里就可以直接使用了,那么有没有什么便捷一点的开关呢,还真有

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

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

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

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

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

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

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

  

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

  

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

github:https://github.com/1024477951/KotlinStrong

posted on 2021-02-03 17:28  翻滚的咸鱼  阅读(515)  评论(0编辑  收藏  举报