The variety of Android devices, with different screen sizes and pixel densities, makes adaptation difficult.

I. Introduction of basic units

Here are some common units in the Android UI.

px

A PX is a pixel, the smallest physical display unit on a screen. For example, a phone resolution of 1080 x 1920 means 1080 pixels wide and 1920 pixels high. A higher resolution screen has more pixels (blocks of color) on it, so it can display a more detailed picture on the screen.

However, don’t use px as a unit for layout, because the display size will be different on different phone resolutions.

You can see that the same PX will display different width and height at different resolutions.

dpi

Dpi is called pixel density, which is the number of points printed per inch. The formula is as follows:


d p i = ( wide 2 + high 2 ) ( p x ) The screen size ( The diagonal ) Dpi =\frac{\ SQRT {(width ^2+ height ^2)(px)} {screen size (diagonal)}

For example, now there is a device “2 inches by 3 inches” :

  • When the device resolution is 320*480, the DPI value is 160
  • When the device resolution is 640*960, the DPI value is 320

So the higher the DPI, the more detailed the screen, and Android also supports qualifiers with different pixel density configurations.

Density qualifier instructions
ldpi Suitable for resources with low density (LDPI) screens (~ 120dpi).
mdpi Resources that apply to medium density (MDPI) screens (~ 160dpi) (this is the baseline density).
hdpi Suitable for high-density (HDPI) screen (~ 240dpi) resources.
xhdpi Suitable for high (XHDPI) density screen (~ 320dpi) resources.
xxhdpi Suitable for super ultra High density (XXHDPI) screen (~ 480dpi) resources.
xxxhdpi Suitable for super ultra High density (XXXHDPI) screen (~ 640dpi) resources.

dp

Dp is a virtual pixel unit, 1 dp is approximately equal to medium density screen (160dpi; 1 pixel on the “base” density). For each other density, Android converts this value to the corresponding actual number of pixels.

Px = dp * (dpi / 160)

Therefore, the same DP value displayed on mobile phones with different resolutions is basically the same size, which is also the official recommended unit.

However, due to fragmentation of Android devices, dp values occupied by width and height are also different for different DPI, so it is impossible to complete adaptation only by DP. For example, the following two images:

The three controls above have a combined width of 360DP, but they look different on phones with different DPI.

Picture 1: Resolution: 1080×2280, screen size: 5.8, DPI: 480, total width: 360DP Picture 2: Resolution: 1080×2240, screen size: 6.2, DPI: 440, total width: 392DP

Use wrap_content, match_parent, and layout_weight as much as possible and use less hard-coded size.

Wrap_content: Adaptive length. The width changes with the content of the control. Match_parent: fills the screen with layout_weight. Controls such as ConstraintLayout can also use a percentage layout

sp

Usually used to specify the font size, which changes when the user modifies the font displayed on the phone.

Two, screen adaptation

Create flexible layouts

To create adaptive layouts for different screen sizes, it is best to use ConstraintLayout as the base layout in an interface. With ConstraintLayout, you can specify the location and size of each view based on the spatial relationships between views in the layout. This way, when the screen size changes, all views can be moved and stretched together.

For more information, see Building an adaptive interface with ConstraintLayout.

Width and height qualifier fit

According to the width and height of the Android phone pixel value, create the corresponding resource file, so as to adapt to different screens.

Set a baseline resolution, and all other resolutions are calculated according to this baseline resolution. In different size folders, write corresponding DIMens files according to this size.

However, there is a major drawback to this solution. Resource files need to be at the same resolution as the phone, and there are so many Android devices that there is no way to write all sizes.

Minimum width qualifier

Using the “minimum width” screen size qualifier, you can provide an alternate layout for screens with the minimum width (measured in density-independent pixels, DP or DIP), which is simply tailored to the width of the phone.

The biggest advantage over width and height qualifiers is backward compatibility. It’s also an officially recommended adaptation,Support for different screen sizes.

Toutiao adaptation scheme

The core of the solution is to change the width DP value of mobile phones with different size resolutions into a unified value, so as to solve the problem of screen adaptation.

The dp value in the layout will eventually be converted to PX, both by calling the applyDimension method of TypedValue:

    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.0 f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0 f/25.4 f);
        }
        return 0;
    }
Copy the code

You can see that the emphasis is on changing the density of the system. Density represents how many pixels 1DP occupies the current device, i.e. Density = dpi / 160, which is fixed on each device.

The core principle of toutiao screen adaptation solution is to modify the density calculation formula:

Density = Total screen width (in pixels)/total design width (in dp)

In this way, we can ensure that the dp values of the width of devices with different resolutions are the same, and then develop directly according to the size of the design drawing, without any other adaptation.

Reference code:

  public static void setCustomDensity(Application application) {
    DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
    // Calculate density, 360 is the total width of the design
    float targetDensity = appDisplayMetrics.widthPixels / 360;
    //计算dpi
    int targetDensityDpi = (int) (160 * targetDensity);

    // Replace system density and DPI
    appDisplayMetrics.density = appDisplayMetrics.scaledDensity = targetDensity;
    appDisplayMetrics.densityDpi = targetDensityDpi;
    DisplayMetrics activityDisplayMerics = activity.getResources().getDisplayMetrics();
    activityDisplayMerics.density = targetDensity;
    activityDisplayMerics.densityDpi = targetDensityDpi;
  }
Copy the code

Effect after modification:

You can see that these three controls fill the entire layout without the aforementioned gaps.

However, this solution has its drawbacks: it’s not very friendly for tablet adaptation, and is essentially an automatic stretch control effect.

AutoSize

A third-party library based on toutiao adaptation solution, github.com/JessYanCodi…

Simple and flexible operation, if using toutiao adaptation scheme, you can directly use the library.

Third, summary

  1. If the UI design is obviously better for wrap_content, match_parent, layout_weight, etc., we should not hesitate to use wrap_content, match_parent, layout_weight, etc., and in the higher dimension, we should make it slippable according to the situation, or match_parent, and try not to write dead.
  2. Build an adaptive interface using ConstraintLayout ConstraintLayout
  3. It can be used only for mobile devicesAutoSizeThird-party library adaptation.
  4. If you need to adapt to tablets, use the minimum width qualifier.

Reference: www.huaweicloud.com/articles/f6…