The previous three screen adaptation concept combed also explained the listed four adaptation scheme, has not seen the children’s shoes can first refer to the three:

Android comprehensive screen adaptation solution analysis (a)__ screen adaptation concept comb

(2)__ width and height qualifier screen adaptation

Android comprehensive screen adaptation scheme parsing (three)__sw qualifier adaptation scheme

Common adaptation schemes are listed as follows:

  • Dp adaptation scheme
  • Width and height qualifier adaptation scheme
  • AndroidAutoLayout adaptation scheme
  • Sw qualifier adaptation scheme
  • Toutiao adaptation scheme
  • AndroidAutoSize adaptation scheme

Here it is necessary to reiterate that some outdated adaptation schemes are also explained here. Each adaptation scheme has its own advantages and disadvantages. From the original adaptation scheme, we can better understand why various adaptation schemes are derived.

Toutiao adaptation scheme

Toutiao adaptation principle analysis

The principle of adaptation solution is to use the formula density = true width of the device (unit px)/ total width of the design drawing (unit DP). When ensuring the total width of the design drawing (unit DP) is fixed, modify the density value to ensure that the true width calculated by all devices with different sizes of resolution is exactly the screen width. This can achieve the purpose of adapting all devices.

For example: let’s say the UI design has a total width of 360DP, and here are two devices with different size resolutions:

Device 1: resolution 1080×1920, DPI is 480, normally calculate density= DPI /160=480/160=3, then the total screen width dp=px/density=1080/3=360;

Device 2: resolution 1440×2560, DPI 560, normally calculate desity= DPI /160=560/160=3.5, then the total screen width dp=px/density=1440/3.5=411;

Normally density is fixed on each device, so if we want to make sure that the total width of the design is 360, let’s take a look at density:

Device 1: resolution 1080×1920, DPI 480, calculated density= real width of the device (px)/ total width of the design drawing (dp) = 1080/360 =3, then the total width of the screen dp=px/density=1080/3=360;

Device 2: resolution 1440×2560, DPI 560, calculated density= real width of device (px)/ total width of design drawing (dp) = 1440/360 = 4, then the total width of screen dp=px/density= 360;

It can be seen from the comparison that the density value can be modified to ensure that the total width of devices with different resolutions is always 360dp, thus ensuring that the UI display effect is consistent on different devices.

Toutiao adaptation scheme derivation process

How to change the density of the system First of all, we need to know that whatever unit value is filled in the layout file, such as 10DP, 10SP, 10px, etc., will eventually be converted to PX by the system. This time, there are children’s ask, how do you know? Of course is through the layout file dp conversion source know.

The applyDimension method of the Typedvalue class is used to convert the dp function:

      / * * *@paramUnit Unit to be converted *@paramValue The value of the unit *@paramMetrics Displays metrics */
	public static float applyDimension(int unit, float value,DisplayMetrics metrics){
        switch (unit) {
        case COMPLEX_UNIT_PX:// The unit is px
            return value;
        case COMPLEX_UNIT_DIP:// The unit is dp
            return value * metrics.density;
        case COMPLEX_UNIT_SP:// The unit is sp
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:// The unit is pt
            return value * metrics.xdpi * (1.0 f/72);
        case COMPLEX_UNIT_IN:// The unit is in
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:// The unit is mm
            return value * metrics.xdpi * (1.0 f/25.4 f);
        }
        return 0;
    }
Copy the code

In the applyDimension method, there is a parameter DisplayMetrics. Let’s see what this parameter means:

 @param metrics Current display metrics to use in the conversion -- supplies display density and scaling information.
Copy the code

This sentence means the current display metric used in the transformation, providing display density and scaling information. Convert via dp in applyDimension method:

public static float applyDimension(int unit, float value,DisplayMetrics metrics){
        switch (unit) {
      	......
        case COMPLEX_UNIT_DIP:// The unit is dp
            returnvalue * metrics.density; . }Copy the code

We can find the density value we need. By tracing the position with The Ctrl key, we can find that this value is a member variable of the system utility class DisplayMetrics, as shown in the figure:

The DisplayMetrics instance can be obtained from the getDisplayMetrics method in the Resources class of the system resource file. The system resource file Resouces can also be obtained from the Activity or Application Context:

DisplayMetrics displayMetrics = this.getResources().getDisplayMetrics();
Copy the code

You can then modify density using the DisplayMetrics instance. Note the effect of the variable scaledDensity, which is the font scaling factor. Normally, it is the same as density, but adjusting the system font size will change this value. Prevents the user from adjusting the system font.

Toutiao’s final solution:

The total width of the design drawing is 360DP, and then we just need to modify our calculated density in the system. The code is as follows:

  	/** * Toutiao adaptation scheme **@param activity
     * @param application
     */
    public static void setCustomDensity(Activity activity, final Application application) {
        // Get DisplayMetrics from the resource file getResources class
        DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
        if (sNoncompatDensity == 0) {
            // Save the previous density value
            sNoncompatDensity = appDisplayMetrics.density;
            // Save the previous value of scaledDensity. ScaledDensity is the scale factor of the font. Normally, it is the same as density, but the value will be changed after adjusting the system font size
            sNoncompatScaledDensity = appDisplayMetrics.scaledDensity;
            // Monitor device system font switch
            application.registerComponentCallbacks(new ComponentCallbacks() {

                public void onConfigurationChanged(Configuration newConfig) {
                    if(newConfig ! =null && newConfig.fontScale > 0) {
                        // Adjust the system font size to change the valuesNoncompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity; }}public void onLowMemory(a) {}}); }// Get the density under the total width of the design drawing 360dp
        float targetDensity = appDisplayMetrics.widthPixels / 360;
        // The scaledDensity value is obtained by calculating the ratio of previous scaledDensity to density
        float targetScaleDensity = targetDensity * (sNoncompatScaledDensity / sNoncompatDensity);
        // Get the dPI value under the total width of the design drawing 360dp
        int targetDensityDpi = (int) (160 * targetDensity);
        // Set the system density
        appDisplayMetrics.density = targetDensity;
        // Set system scaledDensity
        appDisplayMetrics.scaledDensity = targetScaleDensity;
        // Set the densityDpi value
        appDisplayMetrics.densityDpi = targetDensityDpi;

        // Get the DisplayMetrics of the current activity
        final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
        // Set the density of the current activity
        activityDisplayMetrics.density = targetDensity;
        // Set the current activity's scaledDensity value
        activityDisplayMetrics.scaledDensity = targetScaleDensity;
        // Set the densityDpi value for the current activity
        activityDisplayMetrics.densityDpi = targetDensityDpi;
    }
Copy the code

The above code is the final plan of Toutiao. In order to make it easier to read, I just annotated and analyzed it based on my personal understanding. If there is something wrong, please correct it.

Toutiao adaptation steps:

Let’s see how this adaptation works.

1. Layout file, here we use the previous layout, only one picture with width and height of 150×150(dp), as shown below:

<? xml version="1.0" encoding="utf-8"? > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_centerInParent="true"
        android:src="@mipmap/ic_launcher" />

</RelativeLayout>
Copy the code

2. Toutiao adaptation scheme is encapsulated as a tool class, as shown below:

public class CustomDensityUtil {
    private static float sNoncompatDensity;
    private static float sNoncompatScaledDensity;

    /** * Toutiao adaptation scheme **@param activity
     * @param application
     */
    public static void setCustomDensity(Activity activity, final Application application) {
        // Get DisplayMetrics from the resource file getResources class
        DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
        if (sNoncompatDensity == 0) {
            // Save the previous density value
            sNoncompatDensity = appDisplayMetrics.density;
            // Save the previous value of scaledDensity. ScaledDensity is the scale factor of the font. Normally, it is the same as density, but the value will be changed after adjusting the system font size
            sNoncompatScaledDensity = appDisplayMetrics.scaledDensity;
            // Monitor device system font switch
            application.registerComponentCallbacks(new ComponentCallbacks() {

                public void onConfigurationChanged(Configuration newConfig) {
                    if(newConfig ! =null && newConfig.fontScale > 0) {
                        // Adjust the system font size to change the valuesNoncompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity; }}public void onLowMemory(a) {}}); }// Get the density under the total width of the design drawing 360dp
        float targetDensity = appDisplayMetrics.widthPixels / 360;
        // The scaledDensity value is obtained by calculating the ratio of previous scaledDensity to density
        float targetScaleDensity = targetDensity * (sNoncompatScaledDensity / sNoncompatDensity);
        // Get the dPI value under the total width of the design drawing 360dp
        int targetDensityDpi = (int) (160 * targetDensity);
        // Set the system density
        appDisplayMetrics.density = targetDensity;
        // Set system scaledDensity
        appDisplayMetrics.scaledDensity = targetScaleDensity;
        // Set the densityDpi value
        appDisplayMetrics.densityDpi = targetDensityDpi;

        // Get the DisplayMetrics of the current activity
        final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
        // Set the density of the current activity
        activityDisplayMetrics.density = targetDensity;
        // Set the current activity's scaledDensity value
        activityDisplayMetrics.scaledDensity = targetScaleDensity;
        // Set the densityDpi value for the current activityactivityDisplayMetrics.densityDpi = targetDensityDpi; }}Copy the code

3. Call from the onCreate method in the Activity, as shown below:

CustomDensityUtil.setCustomDensity(MainActivity.this, getApplication());
Copy the code

At resolution: 480×800, 720×1280, 1080×1920, 720×1280, 1080×1920

Let’s take a look at the test results of different phones before using toutiao adaptation:

According to the contrast effect before and after adaptation is quite obvious.

Toutiao adaptation scheme advantages

1, very low invasion, and does not involve private API, the solution is completely decoupled from the project, toutiao big factory in use, stability is guaranteed.

2, the use of the cost is very low, simple and convenient operation.

3, access without any performance loss, using the system API.

Toutiao adaptation scheme disadvantages

1. With only one modification of density, all parts of the project will automatically adapt, which seems to free hands and reduce a lot of operations, but actually reflects a disadvantage, that is, the whole project can only be adapted with one knife, but the adaptation scope is not controllable. For example, third-party library controls that are not designed by our project are used in the project, and there will be a very large gap between the size of the design drawing of our project.

2, in use process need to be registerComponentCallbacks listening content text to change the size of the situation, solve the exit after the application to modify text size, size not change would happen.

AndroidAutoSize adaptation scheme

The so-called AndroidAutoSize adaptation scheme is actually an upgraded version of Toutiao adaptation scheme. It is an open source library expanded based on Toutiao adaptation scheme. This library solves the shortcomings of Toutiao adaptation scheme to a large extent and is relatively simple to use. It also supports unadaptation of activities and fragments, which is more flexible.

The following is an example to illustrate the integration process:

Build. Gradle = build.gradle

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io"}}}Copy the code

2. Add the adaptation framework dependency

 implementation 'com. Making. JessYanCoding: AndroidAutoSize: v1.2.1'
Copy the code

3. Indicate the size of the design draft in the AndroidManifest configuration file of the project. Here the test takes 360×640 as an example:

<manifest>
    <application>            
        <meta-data
            android:name="design_width_in_dp"
            android:value="360"/>
        <meta-data
            android:name="design_height_in_dp"
            android:value="640"/>           
     </application>           
</manifest>
Copy the code

If you just want to use the basic functions of the AndroidAutoSize adaptation scheme, the method of using the AndroidAutoSize framework is ended here, just need the above step, can help you access the AndroidAutoSize adaptation framework in the simplest way, I only do the effectiveness of the adaptation scheme demonstration here, Please refer to Github address for details.

4. The test layout file is very simple, only pictures are set. In order to highlight the difference between the test results of toutiao adaptation scheme, the width and height of the picture is set to 120×120(DP), and the test layout is as follows:

<? xml version="1.0" encoding="utf-8"? > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:layout_centerInParent="true"
        android:src="@mipmap/ic_launcher" />

</RelativeLayout>
Copy the code

Let’s take a look at this example and compare it with different phones:

Let’s take a look at the comparison results of different phones before using AndroidAutoSize adaptation:

According to the comparison effect before and after adaptation is quite obvious, AndroidAutoSize adaptation scheme is based on toutiao screen adaptation scheme officially published less than 30 lines of code, after continuous optimization and expansion, developed into now has nearly 20 class files, thousands of lines of code comprehensive screen adaptation framework, In the process of iteration to improve and optimize a lot of functions, compared to toutiao screen adaptation scheme officially announced the original code, AndroidAutoSize adaptation scheme is more stable, more easy to use, more powerful, interested in can go to read the source code, notes are very detailed, here will not do too much introduction, click into the source address

More than six kinds of adaptation scheme explains all over, adaptation framework because the author has explained clearly, I here only explained the basic usage, several other as far as possible all the detail, I explain here did not say which solution is better or worse, the needs of each project is different, suitable is the best. Welcome to pay attention to the public account [Dragon Xuan] can get the latest updates oh.