在撰寫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 = https://www.cnblogs.com/LiuZhen/archive/2021/02/03/(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
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/256288.html
標籤:其他
