Android's simple and easy to use screen adaptation scheme

  • 2021-12-12 09:39:06
  • OfStack

dp in android will convert dp to px before rendering, and the calculation formula is as follows:

px = density * dp; density = dpi / 160; px = dp * (dpi / 160);

1. All our design drawings are designed with fixed sizes. For example, it is designed with resolution 1920px * 1080px and marked with density as 3, that is, the screen is actually 640dp * 360dp. If we want to display complete 1 on all devices, it is actually unrealistic, because the aspect ratio of the screen is not fixed, 16: 9, 4: 3 and even other aspect ratios emerge one after another, and it is impossible to display complete 1 with different aspect ratios. Even if different manufacturers with the same resolution have different screen densities, we need to achieve unified 1.

If you want to do screen adaptation, let's first understand a formula

Conversion formula from dp and px:

px = dp * density

It can be seen that if the design width is 360dp, we can modify the value of density to ensure that the calculated px value on all devices is exactly the screen width. density is a member variable in DisplayMetrics, while DisplayMetrics instances are available through Resources. getDisplayMetrics, and Resouces is available through Activity or Context of Application.

Several variables related to adaptation in DisplayMetrics:

DisplayMetrics. density is the density mentioned above DisplayMetrics. densityDpi is the dpi mentioned above The scaling factor for DisplayMetrics. scaledDensity fonts is normally equal to density, but this value will be changed by adjusting the system font size

We know that no matter what unit system is set, it will eventually be converted to px to calculate and look at the conversion code of the system

TypedValue. applyDimension (int unit, float value, DisplayMetrics metrics) for conversion:

    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;

decode, BitmapFactory. decodeResourceStream methods of pictures

    public static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value,
            @Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) {
        if (opts == null) {
            opts = new Options();

        if (opts.inDensity == 0 && value != null) {
            final int density = value.density;
            if (density == TypedValue.DENSITY_DEFAULT) {
                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
            } else if (density != TypedValue.DENSITY_NONE) {
                opts.inDensity = density;
	//  Used here densityDpi
        if (opts.inTargetDensity == 0 && res != null) {
            opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
        return decodeStream(is, pad, opts);

If we design the screen with 360dp as the standard by default, we should first set the width of view to one and a half of the screen, that is, 180dp, and it should be 540px on the screen with 1080 * 1920. By calculation

density = 1080/360; desity = 3

According to TypedVaule. applyDimens conversion is 180dp * 3 = 540px if it is 720 * 1280 screen 1 half screen width is 360px, we calculate

density = 720/360, density = 2;

According to TypedVaule. applyDimens, it is 180dp * 2 = 360px

Therefore, our final implementation plan is as follows:

    private static final float defaultWidth = 360;
    private static float appDensity;
    private static float appScaleDensity;

    public static void setCustomDensity(Application application, Activity activity){
        DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();
        if (appDensity == 0){
            appDensity = displayMetrics.density;
            appScaleDensity = displayMetrics.scaledDensity;
	        // Set listening after modifying system fonts 
            application.registerComponentCallbacks(new ComponentCallbacks() {
                public void onConfigurationChanged(@NonNull Configuration newConfig) {
                    if (newConfig != null && newConfig.fontScale >0){
                        appScaleDensity = application.getResources().getDisplayMetrics().scaledDensity;

                public void onLowMemory() {

        final float targetDensity = displayMetrics.widthPixels/defaultWidth;
        final float targetScaleDensity = targetDensity *(appScaleDensity/appDensity);
        final int  targetDensityDpi = (int) (targetDensity * 160);
        displayMetrics.density = targetDensity;
        displayMetrics.scaledDensity = targetScaleDensity;
        displayMetrics.densityDpi = targetDensityDpi;
        final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
        activityDisplayMetrics.density = targetDensity;
        activityDisplayMetrics.scaledDensity = targetScaleDensity;
        activityDisplayMetrics.densityDpi = targetDensityDpi;

Use in the project:

    protected void onCreate(Bundle savedInstanceState) {
        // Notice that the call here 1 It must be in setContentView Before 

Point out the shortcomings to everyone and learn together.

The above is the Android simple and easy to use screen adaptation program details, more information about Android screen adaptation please pay attention to other related articles on this site!

Related articles: