A, the present situation

Due to the fragmentation of Android, screen adaptation has always been a headache in development. Facing various screen sizes and resolutions on the market, the Android adaptation scheme based on DP and RES directory names can no longer meet the requirements of writing full-screen adaptation at one time. In order to achieve the optimal visual effect, it is always necessary to spend more resources for adaptation in the development process. Some developers have come up with their own solutions. First, let’s look at the status of some common solutions:

  1. Official adaptation
    • Dp. Dp is a unit unique to Android development. Unlike PX, DP is a unit based on the density of pixels on the screen. Maybe 1DP =1px on a low-density screen, but maybe 1DP =4px on a high-density screen. When writing layout XML, if a control’s width and length are specified using DP, you can ensure that the control is roughly the same absolute size on screens of all sizes and resolutions. In other words, the actual size of the control is the same on both the pad and the phone:



      Figure 1. PNG
    • Resource directory name. As you can see, using DP ensures that the absolute size of the control is the same across screens. The advantage of this is that on a screen of similar size, no matter how large the resolution is, it doesn’t affect the layout; But when screen sizes vary widely, just ensuring the absolute size of the controls can seem problematic. In the RES directory, you can add suffixes such as ‘-1920×1080’ to each resource directory to adapt to different screens. This can provide different layouts for different screens, or even two completely different layouts for the pad and the phone. However, in general, designers do not provide different design drawings for different screens. What they need is the same relative size of controls under different screens. Therefore, DP cannot meet this requirement.

      The usual adaptation we need is something like this:



      Figure 2. The PNG
    • Percentage layout support library. Not used, but deprecated in API level 26.0.0-beta1
    • ConstraintLayout. The layout recommended after the percent support library is deprecated may seem a bit complicated.
  2. Player adaptation schemes. The goal is to make sure that the controls are the same relative size across screens and look exactly the same. Take for example the two adaptations of a great player:
    • One way. The downside of writing a script to convert length to length at all resolutions is that it is difficult to cover all the resolutions available on the market.
    • Scheme 2. AutoLayout support library. The idea of the library is very good: use PX to write the layout against the design without affecting the preview; In the drawing stage, the px numerical calculation of the corresponding design drawing is converted to the appropriate size under the current screen. To simplify access, the view view automatically transforms each Layout into the corresponding AutoLayout while constructing, eliminating the need for changes in all XML. However, the library also has the following problems:
      • Poor scalability. For each ViewGroup to write the corresponding AutoLayout for extension, for each View of each need to adapt the attribute to write code for adaptation extension;
      • Perform numerical calculation in onMeasure phase. This makes a lot of sense for attributes in non-LayoutParams. For example, when converting and setTextSize the TextView’s textSize in onMeasure, the dynamic textSize set by the player in the code will be invalid because it will be overwritten by AutoLayout reset every time onMesasure.
      • There are many issues and the author is no longer maintained.

Second, the idea

Personally, I think the design idea of AutoLayout is very good, but the scheme that takes LayoutParams and attributes as the entry point for conversion calculation in mesure process has problems in efficiency and expansibility. So where is the end of the Android calculation length, can be converted in the Android calculation length? If you can do the conversion while Android calculates the length, then you don’t need a bunch of extra calculations and adaptations, and everything will be all right.

After some searching, it is found that applyDimension function in TypedValue is the end of the length calculation.

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); case COMPLEX_UNIT_MM: return value * metrics. } return 0; }Copy the code
  • You can see that the scaling method is very simple, and all of the properties of DisplayMetrics arepublicCan be modified without reflection;
  • And where does this DisplayMetrics come from? It can be seen from the source code that is generallymContext.getResources().getDisplayMetrics()themContextIs the Activity;
  • The DisplayMetrics obtained in the Activity is not an example of the DisplayMetrics obtained in the Application, but all values are the same, and changes made in the Application will affect all activities;
  • The change of Configuration will lead to the recalculation and restoration of DisplayMetrics, requiring handle.
  • Px, DP and SP are commonly used units, while PT, IN and mm are almost never seen. Starting from these uncommon units can not affect other commonly used units.

Based on the above points, there are the following schemes.

Three,

Use the unpopular pt as a unit of length.

Write the XML exactly as the size on the design, only in pt. To use when dynamic code into the px TypedValue. ApplyDimension (TypedValue.COM PLEX_UNIT_PT, value, the metrics).

The preview. Using 1334×750 bits as an example, create a device that is 1334 pounds long and 750 pounds wide as a preview, which translates to about 21.5 inches ((SQRT (1334^2+750^2))/72). Select this device for preview.





FIG. 3. The PNG




FIG. 4. PNG

Change DisplayMetrics in Application onCreate and onConfigurationChanged:

public class MyApplication extends Application{

    public final static float DESIGN_WIDTH = 750;

    @Override
    public void onCreate() {
        super.onCreate();

        resetDensity();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        resetDensity();
    }

    public void resetDensity(){
        Point size = new Point();
        ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay().getSize(size);

        getResources().getDisplayMetrics().xdpi = size.x/DESIGN_WIDTH*72f;
    }Copy the code

Where DESIGN_WIDTH is the width of the design diagram.

The resulting page looks almost exactly like the design, either large or small, and looks like a zoomed design.

Adapter before:





Figure 5. PNG

After the adapter:





Figure 6. PNG