三方框架必学系列#屏幕适配

137 阅读14分钟

三方框架必学系列#EventBus

三方框架必学系列#Rxjava

三方框架必学系列#Retrofit

三方框架必学系列#OkHttp

三方框架必学系列#Glide

三方框架必学系列#屏幕适配

一.屏幕相关知识

Android屏幕适配由来已久,关键在于屏幕尺寸与屏幕分辨率的变化巨大。

官网:支持不同的像素密度
屏幕尺寸:屏幕对角线的长度(1inch=2.54cm)**
px:像素单位,1px代表1个像素
dpi:像素密度,单位英寸上的像素数量,公式是dpi=屏幕对角线像素总数px/屏幕对角线长度in
density:屏幕密度,规定以160dpi的屏幕其屏幕密度为1,反过来说就是density为1的屏幕上1in上有160px;
分辨率:像素点个数,一般是一纵向x横向 19201080*
dp (像素无关密度的单位) 是根据一个标准来的
比如在

mdpi 160dpi(320x480)的设备上1dp=1px 图标尺寸 48x48px**
hdpi 240dpi(480x800)的设备上1dp=1.5px 图标尺寸 72x72px
xhdpi 320dpi(720x1280)的设备上1dp=2px 图标尺寸 96x96px
xxhdpi 480dpi(1080x1920)的设备上1dp=3px 图标尺寸 144x144px
**xxxhdpi 640dpi(2160x3840)的设备上 1dp=4px 图标尺寸 192x192px

二.适配方案

适配中的问题

  • 相同的density,但是像素不同的设备上,如何达到相同的显示效果!

如: 同样是320 dpi的像素密度,但是像素不同的设备:
density=2,1080px/(320dpi/160) = 540 dp
density=2,720px/(320dpi/160) = 360 dp

在上面的两种设备上,如果我们想要表示宽度为宽度一半,也就是在1080px上的540px和720px上的360px,那怎么表示呢?显然直接用dp和px都无法直接表示!!!那怎么办呢?

1.多px文件适配

提前生成多套px文件到res,设备会根据实际分辨率来读取对应的分辨率文件,如果未找到对应的分辨率,会去找到与它相接近的分辨率(优先从x轴查找)。
举个例子:如果美工切图给720p,也就是7201280px的分辨率,那我们就以72** 1280为基准生成px文件,其他的分辨率文件会以7201280进行相对应的缩放。当我们在720p设备上设置某张图片的宽度为360px时,他会去1080 720的dimens上查找lay_x上x360对应的宽也就是360px,,而在1080p上他会在19201080的dimens上查找lay_x上x360对应的宽也就是540px,这样通过在不同分辨率的dimens中,但文件名相同像素大小不同,从而达到显示比例效果一致了。

运行以下代码即可生成对应分辨率的文件

package com.seven.screenadater;

import androidx.annotation.NonNull;

import org.junit.Test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;

/**
 * Time: 2025/7/24
 * <p>
 * Author: seven
 * <p>
 * Description: 多 px文件生成工具
 */

public class GenerateValueFiles {


    private int baseW;
    private int baseH;

    //    private String dirStr = "./res"; //生成路径
    private String dirStr = "./src/main/res"; //生成路径
    private final static String WTemplate = "<dimen name="x{0}">{1}px</dimen>\n";
    private final static String HTemplate = "<dimen name="y{0}">{1}px</dimen>\n";

    /**
     * {0}-HEIGHT
     */
    private final static String VALUE_TEMPLATE = "values-{0}x{1}";

    private static final String SUPPORT_DIMESION = "720,1080;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;";

    private String supportStr = SUPPORT_DIMESION;
    public GenerateValueFiles() {

    }
    public GenerateValueFiles(int baseX, int baseY, String supportStr) {
        this.baseW = baseX;
        this.baseH = baseY;

        if (!this.supportStr.contains(baseX + "," + baseY)) {
            this.supportStr += baseX + "," + baseY + ";";
        }

        this.supportStr += validateInput(supportStr);

        System.out.println(supportStr);

        File dir = new File(dirStr);
        if (!dir.exists()) {
            dir.mkdir();

        }
        System.out.println(dir.getAbsoluteFile());

    }

    /**
     * @param supportStr
     *            w,h_...w,h;
     * @return
     */
    private String validateInput(String supportStr) {
        StringBuffer sb = new StringBuffer();
        String[] vals = supportStr.split("_");
        int w = -1;
        int h = -1;
        String[] wh;
        for (String val : vals) {
            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 invalidate params : w,h = " + val);
                continue;
            }
            sb.append(w + "," + h + ";");
        }

        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) {

        StringBuffer sbForWidth = new StringBuffer();
        sbForWidth.append("<?xml version="1.0" encoding="utf-8"?>\n");
        sbForWidth.append("<resources>");
        float cellw = w * 1.0f / baseW;

        System.out.println("width : " + w + "," + baseW + "," + cellw);
        for (int i = 1; i < baseW; i++) {
            sbForWidth.append(WTemplate.replace("{0}", i + "").replace("{1}",
                    change(cellw * i) + ""));
        }
        sbForWidth.append(WTemplate.replace("{0}", baseW + "").replace("{1}",
                w + ""));
        sbForWidth.append("</resources>");

        StringBuffer sbForHeight = new StringBuffer();
        sbForHeight.append("<?xml version="1.0" encoding="utf-8"?>\n");
        sbForHeight.append("<resources>");
        float cellh = h *1.0f/ baseH;
        System.out.println("height : "+ h + "," + baseH + "," + cellh);
        for (int i = 1; i < baseH; i++) {
            sbForHeight.append(HTemplate.replace("{0}", i + "").replace("{1}",
                    change(cellh * i) + ""));
        }
        sbForHeight.append(HTemplate.replace("{0}", baseH + "").replace("{1}",
                h + ""));
        sbForHeight.append("</resources>");

        File fileDir = new File(dirStr + File.separator
                + VALUE_TEMPLATE.replace("{0}", h + "")//
                .replace("{1}", w + ""));
        fileDir.mkdir();

        File layxFile = new File(fileDir.getAbsolutePath(), "lay_x.xml");
        File layyFile = new File(fileDir.getAbsolutePath(), "lay_y.xml");
        try {
            PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile));
            pw.print(sbForWidth.toString());
            pw.close();
            pw = new PrintWriter(new FileOutputStream(layyFile));
            pw.print(sbForHeight.toString());
            pw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static float change(float a) {
        int temp = (int) (a * 100);
        return temp / 100f;
    }


    public  void test(@NonNull String[] args) {
        //设计尺寸基准,假设给的是像素为720*1280
        int baseW = 720;
        int baseH = 1280;
        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();
    }
}

不过这个方案需要预制进去所有的不同分辨率的文件。

2.smallestwidth适配

这个方案和px原理差不多,只不过这个是以dp为基准来生成不同的dp文件,不同dp的设备会去到对应的dp文件中查找宽度和高度。一般我们用最小的宽度为360dp为基准,如果美工给的是360dp规格的效果图和切图更好,但如果美工以720 x1280的像素效果图和切图给你,你需要换算下你设置的切图大小,比如有一个图片美工给你的标注的宽度的是360px,那你设置的就是360/720*360=180,换算的时候,你可以把你的基准认为成要用多少等分表示效果图的像素,比如这里用360等分来表示720个像素,那么1个等分也就是2个像素。上面的18dp在360dp上所占的宽度比例为180/360=1/2,在最小宽度为540dp的设备上,他的就会是270/540,也就是占总宽度的1/2,同样的比例让他们显示的效果一致。

如何生成这些dp文件和设置标准呢?

使用screenMatch这个插件就可以生成**
**1.在 Android Studio 中安装 ScreenMatch 插件

2.在项目的默认 values 文件夹中需要一份 dimens.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<resources>

  <!-- Your custom size defind by references, can be writted in anywhere, any module, any values/*.xml, for example: -->
  <dimen name="common_margin">@dimen/dp_15</dimen>

  <!-- dp and sp values, must be defind in this file! -->
  <!-- view size,you can add if there is no one -->
  <dimen name="dp_m_60">-60dp</dimen>
  <dimen name="dp_m_30">-30dp</dimen>
  <dimen name="dp_m_20">-20dp</dimen>
  <dimen name="dp_m_12">-12dp</dimen>
  <dimen name="dp_m_10">-10dp</dimen>
  <dimen name="dp_m_8">-8dp</dimen>
  <dimen name="dp_m_5">-5dp</dimen>
  <dimen name="dp_m_2">-2dp</dimen>
  <dimen name="dp_m_1">-1dp</dimen>
  <dimen name="dp_0">0dp</dimen>
  <dimen name="dp_0_1">0.1dp</dimen>
  <dimen name="dp_0_5">0.5dp</dimen>
  <dimen name="dp_1">1dp</dimen>
  <dimen name="dp_1_5">1.5dp</dimen>
  <dimen name="dp_2">2dp</dimen>
  <dimen name="dp_2_5">2.5dp</dimen>
  <dimen name="dp_3">3dp</dimen>
  <dimen name="dp_3_5">3.5dp</dimen>
  <dimen name="dp_4">4dp</dimen>
  <dimen name="dp_4_5">4.5dp</dimen>
  <dimen name="dp_5">5dp</dimen>
  <dimen name="dp_6">6dp</dimen>
  <dimen name="dp_7">7dp</dimen>
  <dimen name="dp_8">8dp</dimen>
  <dimen name="dp_9">9dp</dimen>
  <dimen name="dp_10">10dp</dimen>
  <dimen name="dp_11">11dp</dimen>
  <dimen name="dp_12">12dp</dimen>
  <dimen name="dp_13">13dp</dimen>
  <dimen name="dp_14">14dp</dimen>
  <dimen name="dp_15">15dp</dimen>
  <dimen name="dp_16">16dp</dimen>
  <dimen name="dp_17">17dp</dimen>
  <dimen name="dp_18">18dp</dimen>
  <dimen name="dp_19">19dp</dimen>
  <dimen name="dp_20">20dp</dimen>
  <dimen name="dp_21">21dp</dimen>
  <dimen name="dp_22">22dp</dimen>
  <dimen name="dp_23">23dp</dimen>
  <dimen name="dp_24">24dp</dimen>
  <dimen name="dp_25">25dp</dimen>
  <dimen name="dp_26">26dp</dimen>
  <dimen name="dp_27">27dp</dimen>
  <dimen name="dp_28">28dp</dimen>
  <dimen name="dp_29">29dp</dimen>
  <dimen name="dp_30">30dp</dimen>
  <dimen name="dp_31">31dp</dimen>
  <dimen name="dp_32">32dp</dimen>
  <dimen name="dp_33">33dp</dimen>
  <dimen name="dp_34">34dp</dimen>
  <dimen name="dp_35">35dp</dimen>
  <dimen name="dp_36">36dp</dimen>
  <dimen name="dp_37">37dp</dimen>
  <dimen name="dp_38">38dp</dimen>
  <dimen name="dp_39">39dp</dimen>
  <dimen name="dp_40">40dp</dimen>
  <dimen name="dp_41">41dp</dimen>
  <dimen name="dp_42">42dp</dimen>
  <dimen name="dp_43">43dp</dimen>
  <dimen name="dp_44">44dp</dimen>
  <dimen name="dp_45">45dp</dimen>
  <dimen name="dp_46">46dp</dimen>
  <dimen name="dp_47">47dp</dimen>
  <dimen name="dp_48">48dp</dimen>
  <dimen name="dp_49">49dp</dimen>
  <dimen name="dp_50">50dp</dimen>
  <dimen name="dp_51">51dp</dimen>
  <dimen name="dp_52">52dp</dimen>
  <dimen name="dp_53">53dp</dimen>
  <dimen name="dp_54">54dp</dimen>
  <dimen name="dp_55">55dp</dimen>
  <dimen name="dp_56">56dp</dimen>
    <dimen name="dp_57">57dp</dimen>
    <dimen name="dp_58">58dp</dimen>
    <dimen name="dp_59">59dp</dimen>
    <dimen name="dp_60">60dp</dimen>
    <dimen name="dp_61">61dp</dimen>
    <dimen name="dp_62">62dp</dimen>
    <dimen name="dp_63">63dp</dimen>
    <dimen name="dp_64">64dp</dimen>
    <dimen name="dp_65">65dp</dimen>
    <dimen name="dp_66">66dp</dimen>
    <dimen name="dp_67">67dp</dimen>
    <dimen name="dp_68">68dp</dimen>
    <dimen name="dp_69">69dp</dimen>
    <dimen name="dp_70">70dp</dimen>
    <dimen name="dp_71">71dp</dimen>
    <dimen name="dp_72">72dp</dimen>
    <dimen name="dp_73">73dp</dimen>
    <dimen name="dp_74">74dp</dimen>
    <dimen name="dp_75">75dp</dimen>
    <dimen name="dp_76">76dp</dimen>
    <dimen name="dp_77">77dp</dimen>
    <dimen name="dp_78">78dp</dimen>
    <dimen name="dp_79">79dp</dimen>
    <dimen name="dp_80">80dp</dimen>
    <dimen name="dp_81">81dp</dimen>
    <dimen name="dp_82">82dp</dimen>
    <dimen name="dp_83">83dp</dimen>
    <dimen name="dp_84">84dp</dimen>
    <dimen name="dp_85">85dp</dimen>
    <dimen name="dp_86">86dp</dimen>
    <dimen name="dp_87">87dp</dimen>
    <dimen name="dp_88">88dp</dimen>
    <dimen name="dp_89">89dp</dimen>
    <dimen name="dp_90">90dp</dimen>
    <dimen name="dp_91">91dp</dimen>
    <dimen name="dp_92">92dp</dimen>
    <dimen name="dp_93">93dp</dimen>
    <dimen name="dp_94">94dp</dimen>
    <dimen name="dp_95">95dp</dimen>
    <dimen name="dp_96">96dp</dimen>
    <dimen name="dp_97">97dp</dimen>
    <dimen name="dp_98">98dp</dimen>
    <dimen name="dp_99">99dp</dimen>
    <dimen name="dp_100">100dp</dimen>
    <dimen name="dp_101">101dp</dimen>
    <dimen name="dp_102">102dp</dimen>
    <dimen name="dp_103">103dp</dimen>
    <dimen name="dp_104">104dp</dimen>
    <dimen name="dp_105">105dp</dimen>
    <dimen name="dp_106">106dp</dimen>
    <dimen name="dp_107">107dp</dimen>
    <dimen name="dp_108">108dp</dimen>
    <dimen name="dp_109">109dp</dimen>
    <dimen name="dp_110">110dp</dimen>
    <dimen name="dp_111">111dp</dimen>
    <dimen name="dp_112">112dp</dimen>
    <dimen name="dp_113">113dp</dimen>
    <dimen name="dp_114">114dp</dimen>
    <dimen name="dp_115">115dp</dimen>
    <dimen name="dp_116">116dp</dimen>
    <dimen name="dp_117">117dp</dimen>
    <dimen name="dp_118">118dp</dimen>
    <dimen name="dp_119">119dp</dimen>
    <dimen name="dp_120">120dp</dimen>
    <dimen name="dp_121">121dp</dimen>
    <dimen name="dp_122">122dp</dimen>
    <dimen name="dp_123">123dp</dimen>
    <dimen name="dp_124">124dp</dimen>
    <dimen name="dp_125">125dp</dimen>
    <dimen name="dp_126">126dp</dimen>
    <dimen name="dp_127">127dp</dimen>
    <dimen name="dp_128">128dp</dimen>
    <dimen name="dp_129">129dp</dimen>
    <dimen name="dp_130">130dp</dimen>
    <dimen name="dp_131">131dp</dimen>
    <dimen name="dp_132">132dp</dimen>
    <dimen name="dp_133">133dp</dimen>
    <dimen name="dp_134">134dp</dimen>
    <dimen name="dp_135">135dp</dimen>
    <dimen name="dp_136">136dp</dimen>
    <dimen name="dp_137">137dp</dimen>
    <dimen name="dp_138">138dp</dimen>
    <dimen name="dp_139">139dp</dimen>
    <dimen name="dp_140">140dp</dimen>
    <dimen name="dp_141">141dp</dimen>
    <dimen name="dp_142">142dp</dimen>
    <dimen name="dp_143">143dp</dimen>
    <dimen name="dp_144">144dp</dimen>
    <dimen name="dp_145">145dp</dimen>
    <dimen name="dp_146">146dp</dimen>
    <dimen name="dp_147">147dp</dimen>
    <dimen name="dp_148">148dp</dimen>
    <dimen name="dp_149">149dp</dimen>
    <dimen name="dp_150">150dp</dimen>
    <dimen name="dp_151">151dp</dimen>
    <dimen name="dp_152">152dp</dimen>
    <dimen name="dp_153">153dp</dimen>
    <dimen name="dp_154">154dp</dimen>
    <dimen name="dp_155">155dp</dimen>
    <dimen name="dp_156">156dp</dimen>
    <dimen name="dp_157">157dp</dimen>
    <dimen name="dp_158">158dp</dimen>
    <dimen name="dp_159">159dp</dimen>
    <dimen name="dp_160">160dp</dimen>
    <dimen name="dp_161">161dp</dimen>
    <dimen name="dp_162">162dp</dimen>
    <dimen name="dp_163">163dp</dimen>
    <dimen name="dp_164">164dp</dimen>
    <dimen name="dp_165">165dp</dimen>
    <dimen name="dp_166">166dp</dimen>
    <dimen name="dp_167">167dp</dimen>
    <dimen name="dp_168">168dp</dimen>
    <dimen name="dp_169">169dp</dimen>
    <dimen name="dp_170">170dp</dimen>
    <dimen name="dp_171">171dp</dimen>
    <dimen name="dp_172">172dp</dimen>
    <dimen name="dp_173">173dp</dimen>
    <dimen name="dp_174">174dp</dimen>
    <dimen name="dp_175">175dp</dimen>
    <dimen name="dp_176">176dp</dimen>
    <dimen name="dp_177">177dp</dimen>
    <dimen name="dp_178">178dp</dimen>
    <dimen name="dp_179">179dp</dimen>
    <dimen name="dp_180">180dp</dimen>
    <dimen name="dp_181">181dp</dimen>
    <dimen name="dp_182">182dp</dimen>
    <dimen name="dp_183">183dp</dimen>
    <dimen name="dp_184">184dp</dimen>
    <dimen name="dp_185">185dp</dimen>
    <dimen name="dp_186">186dp</dimen>
    <dimen name="dp_187">187dp</dimen>
    <dimen name="dp_188">188dp</dimen>
    <dimen name="dp_189">189dp</dimen>
    <dimen name="dp_190">190dp</dimen>
    <dimen name="dp_191">191dp</dimen>
    <dimen name="dp_192">192dp</dimen>
    <dimen name="dp_193">193dp</dimen>
    <dimen name="dp_194">194dp</dimen>
    <dimen name="dp_195">195dp</dimen>
    <dimen name="dp_196">196dp</dimen>
    <dimen name="dp_197">197dp</dimen>
    <dimen name="dp_198">198dp</dimen>
    <dimen name="dp_199">199dp</dimen>
    <dimen name="dp_200">200dp</dimen>
    <dimen name="dp_201">201dp</dimen>
    <dimen name="dp_202">202dp</dimen>
    <dimen name="dp_203">203dp</dimen>
    <dimen name="dp_204">204dp</dimen>
    <dimen name="dp_205">205dp</dimen>
    <dimen name="dp_206">206dp</dimen>
    <dimen name="dp_207">207dp</dimen>
    <dimen name="dp_208">208dp</dimen>
    <dimen name="dp_209">209dp</dimen>
    <dimen name="dp_210">210dp</dimen>
    <dimen name="dp_211">211dp</dimen>
    <dimen name="dp_212">212dp</dimen>
    <dimen name="dp_213">213dp</dimen>
    <dimen name="dp_214">214dp</dimen>
    <dimen name="dp_215">215dp</dimen>
    <dimen name="dp_216">216dp</dimen>
    <dimen name="dp_217">217dp</dimen>
    <dimen name="dp_218">218dp</dimen>
    <dimen name="dp_219">219dp</dimen>
    <dimen name="dp_220">220dp</dimen>
    <dimen name="dp_221">221dp</dimen>
    <dimen name="dp_222">222dp</dimen>
    <dimen name="dp_223">223dp</dimen>
    <dimen name="dp_224">224dp</dimen>
    <dimen name="dp_225">225dp</dimen>
    <dimen name="dp_226">226dp</dimen>
    <dimen name="dp_227">227dp</dimen>
    <dimen name="dp_228">228dp</dimen>
    <dimen name="dp_229">229dp</dimen>
    <dimen name="dp_230">230dp</dimen>
    <dimen name="dp_231">231dp</dimen>
    <dimen name="dp_232">232dp</dimen>
    <dimen name="dp_233">233dp</dimen>
    <dimen name="dp_234">234dp</dimen>
    <dimen name="dp_235">235dp</dimen>
    <dimen name="dp_236">236dp</dimen>
    <dimen name="dp_237">237dp</dimen>
    <dimen name="dp_238">238dp</dimen>
    <dimen name="dp_239">239dp</dimen>
    <dimen name="dp_240">240dp</dimen>
    <dimen name="dp_241">241dp</dimen>
    <dimen name="dp_242">242dp</dimen>
    <dimen name="dp_243">243dp</dimen>
    <dimen name="dp_244">244dp</dimen>
    <dimen name="dp_245">245dp</dimen>
    <dimen name="dp_246">246dp</dimen>
    <dimen name="dp_247">247dp</dimen>
    <dimen name="dp_248">248dp</dimen>
    <dimen name="dp_249">249dp</dimen>
    <dimen name="dp_250">250dp</dimen>
    <dimen name="dp_251">251dp</dimen>
    <dimen name="dp_252">252dp</dimen>
    <dimen name="dp_253">253dp</dimen>
    <dimen name="dp_254">254dp</dimen>
    <dimen name="dp_255">255dp</dimen>
    <dimen name="dp_256">256dp</dimen>
    <dimen name="dp_257">257dp</dimen>
    <dimen name="dp_258">258dp</dimen>
    <dimen name="dp_259">259dp</dimen>
    <dimen name="dp_260">260dp</dimen>
    <dimen name="dp_261">261dp</dimen>
    <dimen name="dp_262">262dp</dimen>
    <dimen name="dp_263">263dp</dimen>
    <dimen name="dp_264">264dp</dimen>
    <dimen name="dp_265">265dp</dimen>
    <dimen name="dp_266">266dp</dimen>
    <dimen name="dp_267">267dp</dimen>
    <dimen name="dp_268">268dp</dimen>
    <dimen name="dp_269">269dp</dimen>
    <dimen name="dp_270">270dp</dimen>
    <dimen name="dp_271">271dp</dimen>
    <dimen name="dp_272">272dp</dimen>
    <dimen name="dp_273">273dp</dimen>
    <dimen name="dp_274">274dp</dimen>
    <dimen name="dp_275">275dp</dimen>
    <dimen name="dp_276">276dp</dimen>
    <dimen name="dp_277">277dp</dimen>
    <dimen name="dp_278">278dp</dimen>
    <dimen name="dp_279">279dp</dimen>
    <dimen name="dp_280">280dp</dimen>
    <dimen name="dp_281">281dp</dimen>
    <dimen name="dp_282">282dp</dimen>
    <dimen name="dp_283">283dp</dimen>
    <dimen name="dp_284">284dp</dimen>
    <dimen name="dp_285">285dp</dimen>
    <dimen name="dp_286">286dp</dimen>
    <dimen name="dp_287">287dp</dimen>
    <dimen name="dp_288">288dp</dimen>
    <dimen name="dp_289">289dp</dimen>
    <dimen name="dp_290">290dp</dimen>
    <dimen name="dp_291">291dp</dimen>
    <dimen name="dp_292">292dp</dimen>
    <dimen name="dp_293">293dp</dimen>
    <dimen name="dp_294">294dp</dimen>
    <dimen name="dp_295">295dp</dimen>
    <dimen name="dp_296">296dp</dimen>
    <dimen name="dp_297">297dp</dimen>
    <dimen name="dp_298">298dp</dimen>
    <dimen name="dp_299">299dp</dimen>
    <dimen name="dp_300">300dp</dimen>
    <dimen name="dp_301">301dp</dimen>
    <dimen name="dp_302">302dp</dimen>
    <dimen name="dp_303">303dp</dimen>
    <dimen name="dp_304">304dp</dimen>
    <dimen name="dp_305">305dp</dimen>
    <dimen name="dp_306">306dp</dimen>
    <dimen name="dp_307">307dp</dimen>
    <dimen name="dp_308">308dp</dimen>
    <dimen name="dp_309">309dp</dimen>
    <dimen name="dp_310">310dp</dimen>
    <dimen name="dp_311">311dp</dimen>
    <dimen name="dp_312">312dp</dimen>
    <dimen name="dp_313">313dp</dimen>
    <dimen name="dp_314">314dp</dimen>
    <dimen name="dp_315">315dp</dimen>
    <dimen name="dp_316">316dp</dimen>
    <dimen name="dp_317">317dp</dimen>
    <dimen name="dp_318">318dp</dimen>
    <dimen name="dp_319">319dp</dimen>
    <dimen name="dp_320">320dp</dimen>
    <dimen name="dp_321">321dp</dimen>
    <dimen name="dp_322">322dp</dimen>
    <dimen name="dp_323">323dp</dimen>
    <dimen name="dp_324">324dp</dimen>
    <dimen name="dp_325">325dp</dimen>
    <dimen name="dp_326">326dp</dimen>
    <dimen name="dp_327">327dp</dimen>
    <dimen name="dp_328">328dp</dimen>
    <dimen name="dp_329">329dp</dimen>
    <dimen name="dp_330">330dp</dimen>
    <dimen name="dp_331">331dp</dimen>
    <dimen name="dp_332">332dp</dimen>
    <dimen name="dp_333">333dp</dimen>
    <dimen name="dp_334">334dp</dimen>
    <dimen name="dp_335">335dp</dimen>
    <dimen name="dp_336">336dp</dimen>
    <dimen name="dp_337">337dp</dimen>
    <dimen name="dp_338">338dp</dimen>
    <dimen name="dp_339">339dp</dimen>
    <dimen name="dp_340">340dp</dimen>
    <dimen name="dp_341">341dp</dimen>
    <dimen name="dp_342">342dp</dimen>
    <dimen name="dp_343">343dp</dimen>
    <dimen name="dp_344">344dp</dimen>
    <dimen name="dp_345">345dp</dimen>
    <dimen name="dp_346">346dp</dimen>
    <dimen name="dp_347">347dp</dimen>
    <dimen name="dp_348">348dp</dimen>
    <dimen name="dp_349">349dp</dimen>
    <dimen name="dp_350">350dp</dimen>
    <dimen name="dp_351">351dp</dimen>
    <dimen name="dp_352">352dp</dimen>
    <dimen name="dp_353">353dp</dimen>
    <dimen name="dp_354">354dp</dimen>
    <dimen name="dp_355">355dp</dimen>
    <dimen name="dp_356">356dp</dimen>
    <dimen name="dp_357">357dp</dimen>
    <dimen name="dp_358">358dp</dimen>
    <dimen name="dp_359">359dp</dimen>
    <dimen name="dp_360">360dp</dimen>
<!--    <dimen name="dp_365">365dp</dimen>-->
<!--    <dimen name="dp_370">370dp</dimen>-->
<!--    <dimen name="dp_400">400dp</dimen>-->
<!--    <dimen name="dp_410">410dp</dimen>-->
<!--    <dimen name="dp_422">422dp</dimen>-->
<!--    <dimen name="dp_472">472dp</dimen>-->
<!--    <dimen name="dp_500">500dp</dimen>-->
<!--    <dimen name="dp_600">600dp</dimen>-->
<!--    <dimen name="dp_640">640dp</dimen>-->
<!--    <dimen name="dp_720">720dp</dimen>-->

    <!-- font size,you can add if there is no one -->
    <dimen name="sp_6">6sp</dimen>
    <dimen name="sp_7">7sp</dimen>
    <dimen name="sp_8">8sp</dimen>
    <dimen name="sp_9">9sp</dimen>
    <dimen name="sp_10">10sp</dimen>
    <dimen name="sp_11">11sp</dimen>
    <dimen name="sp_12">12sp</dimen>
    <dimen name="sp_13">13sp</dimen>
    <dimen name="sp_14">14sp</dimen>
    <dimen name="sp_15">15sp</dimen>
    <dimen name="sp_16">16sp</dimen>
    <dimen name="sp_17">17sp</dimen>
    <dimen name="sp_18">18sp</dimen>
    <dimen name="sp_19">19sp</dimen>
    <dimen name="sp_20">20sp</dimen>
    <dimen name="sp_21">21sp</dimen>
    <dimen name="sp_22">22sp</dimen>
    <dimen name="sp_23">23sp</dimen>
    <dimen name="sp_24">24sp</dimen>
    <dimen name="sp_25">25sp</dimen>
    <dimen name="sp_28">28sp</dimen>
    <dimen name="sp_30">30sp</dimen>
    <dimen name="sp_32">32sp</dimen>
    <dimen name="sp_34">34sp</dimen>
    <dimen name="sp_36">36sp</dimen>
    <dimen name="sp_38">38sp</dimen>
    <dimen name="sp_40">40sp</dimen>
    <dimen name="sp_42">42sp</dimen>
    <dimen name="sp_48">48sp</dimen>

</resources>

3.选择项目,使用插件生成不同dp文件。

4.修改默认的dp基准和一些其他参数

3.density适配

我们不管在布局中写什么单位,最后都会被转化为 px,系统就是通过下面的方法,将你在项目中任何地方填写的单位都转换为 px 的,所以我们常用的 px 转 dp 的公式 dp = px / density,就是根据上面的方法得来的。

public static float applyDimension(int unit, float value,
                                   DisplayMetrics metrics)
{
    switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
    }
    return 0;
}

所以,修改density适配这种方案的原理主要是修改activity的density来达到显示效果一致,如果UI给的规格是360dp。当在density为3,宽度为1080px的设备上,它的dp值=宽度像素/density=360dp,在density为4,宽度为2160px的设备上,它的dp值为540dp,我们想要表示宽度为总宽度的一半控件,怎么表示呢?如果用上面那两种多套px和多套dp方案,就需要通过生成不同的px文件和dp文件,而在这种方案中,我们肯定使用180dp来设置宽度的,在1080px density为3的设备上 180dp的像素为px=density * dp=180 * 3=540px刚好为总宽度的一半,而在density为4 宽度2160px的设备上,如果你仍然用180dp来设置控件的宽度,他的px=density * dp=180 * 4=720px,很显然他没有到总宽度的一半,这个时候我们需要修改下他的density,他的density计算方式为宽度总像素/设计规格=2160px/360dp=6,这样上面的180dp在这个设备上表示的像素px为:180dp * 6=1080px,也就达到一半的效果了。具体代码如下:

public class DensityUtils {

    //ui设计的标准dp
    public static final int STANDARD_WIDTH = 360;
    //系统原来的像素缩放比
    private static float appDensity;
    private static float appScaleDensity;   //字体缩放比

    public static void setDensity(final Application application, Activity activity) {
        final DisplayMetrics appMetrics = application.getResources().getDisplayMetrics();
        if (appDensity == 0) {
            //获取系统本来的像素缩放比和字体缩放比
            appDensity = appMetrics.density;
            System.out.println("setDensity origin:" + appDensity);
            appScaleDensity = appMetrics.scaledDensity;
        }

        if (null != application) {
            application.registerComponentCallbacks(new ComponentCallbacks() {
                @Override
                public void onConfigurationChanged(Configuration newConfig) {
                    //代表字体大小进行了更改,需要对字体缩放比进行重新赋值
                    if (newConfig != null && newConfig.fontScale > 0) {
                        appScaleDensity = application.getResources().getDisplayMetrics().scaledDensity;
                    }
                }

                @Override
                public void onLowMemory() {

                }
            });
        }
        //320dpi 1dp=2px  density=2
        //通过实际的屏幕大小来计算新的屏幕像素缩放比
        float targetDensity = appMetrics.widthPixels / STANDARD_WIDTH;

        float targetScaleDensity = targetDensity * (appScaleDensity / appDensity);
        System.out.println("setDensity targetScaleDensity:" + targetScaleDensity);
        float targetDensityDpi = targetDensity * 160;

        //将获取到的新的缩放比设置回去
        DisplayMetrics actMetrics = activity.getResources().getDisplayMetrics();
        actMetrics.density = targetDensity;
        actMetrics.densityDpi = (int) targetDensityDpi;
        actMetrics.scaledDensity = targetScaleDensity;

    }

    /**
     * webView初始化会还原density
     *
     * @return
     */
    public static float getAppDensity(Application application) {
        final DisplayMetrics appMetrics = application.getResources().getDisplayMetrics();
        System.out.println("getAppDensity densityDpi:" + appMetrics.densityDpi + ",density:"
                + appMetrics.density + ",scaledDensity:" + appMetrics.scaledDensity);
        return appMetrics.density;
    }


    /**
     * webView初始化会还原density
     *
     * @param activity
     * @return
     */
    public static float getActivityDensity(Activity activity) {
        final DisplayMetrics appMetrics = activity.getResources().getDisplayMetrics();
        System.out.println("getActivityDensity densityDpi:" + appMetrics.densityDpi + ",density:"
                + appMetrics.density + ",scaledDensity:" + appMetrics.scaledDensity+",xdpi:"+appMetrics.xdpi);
        return appMetrics.density;
    }

    /**
     * Toast弹框show之前需要恢复,不然大小会缩放
     * @param activity
     */
    public static void restoreScreen(final Activity activity) {
        final DisplayMetrics systemDm = Resources.getSystem().getDisplayMetrics();
        final DisplayMetrics activityDm = activity.getResources().getDisplayMetrics();
        activityDm.density = systemDm.density;
        activityDm.scaledDensity = systemDm.scaledDensity;
        activityDm.densityDpi = systemDm.densityDpi;
        System.out.println("restoreScreen densityDpi:" + systemDm.densityDpi + ",density:"
                + systemDm.density + ",scaledDensity:" + systemDm.scaledDensity);

    }

注意事项:

1.由于 WebView 初始化的时候会还原 density 的值导致适配失效,继承 WebView,重写如下方法:

       @Override
       public void setOverScrollMode(int mode){
         super.setOverScrollMode(mode);
        DensityUtils.setDensity(App.getInstance(),activity);
       }

2.适配之后Toast的问题?
进行上面的适配之后,Toast会变得很小。其实也不难理解,因为你修改了APP的density,所以整个图片的界面都会发生相应的变化也就很好理解了。那么怎么解决呢?其实就想上面说的,
使用System的density对App和Activity进行还原。怎么说呢?其实就是在show()方法之前还原,在之后在进行适配。

三.其他第三方屏幕适配方案

基于修改density的第三方屏幕适配方案,有兴趣可以看看:
androidAutoSize
blankj