A rough and fast Android full-screen adaptation solution

A rough and fast Android full-screen adaptation solution

1. Current situation

Due to the serious fragmentation of Android, screen adaptation has always been a headache in development. Faced with the various screen sizes and resolutions on the market, Android's adaptation solution based on dp and res directory names can no longer meet the needs of writing full-screen adaptation at one time. In order to achieve the best visual effects, more resources are always required for adaptation during the development process. Some developers have also provided some of their own solutions. First, let's analyze the current status of some common solutions:

Official adaptation solution

dp. dp is a unit unique to Android development. Unlike px, dp is a unit based on screen pixel density. On a low-density screen, 1dp=1px may be 1dp=4px, but on a high-density screen, 1dp=4px may be 1dp=1px. When writing layout xml, if the length and width of a control are specified using dp, it can ensure that the absolute size of the control is roughly the same on screens of various sizes and resolutions. In other words, whether on a pad or a large or small screen phone, the size of the control we actually see is similar:

Resource directory name. As can be seen in the figure above, although dp is used to ensure that the absolute size of the control is consistent on different screens. The advantage of this is that in screens of similar size, no matter how large the resolution is, it will not affect the layout; but when the screen sizes differ greatly, it seems a bit problematic to only ensure the absolute size of the control. In the res directory, you can add suffixes such as '-1920x1080' to each resource directory to adapt to different screens. For specific rules, see the official website document. In this way, different layouts can be provided for different screens, and even two completely different layout styles can be provided for pads and mobile phones. However, usually, designers do not provide different design drawings for different screens. Their only requirement is that the relative size of the control on different screens is consistent, so dp cannot meet this requirement, and adapting to various screens is a bit cumbersome, and modification is also more troublesome. Usually the adaptation we need is like this:

Percentage layout support library. Not used, but deprecated in API level 26.0.0-beta1.

ConstraintLayout. The recommended layout after the percentage support library is deprecated, it seems a bit complicated.

Player adaptation scheme. The purpose of the majority of players' adaptation is very clear, which is to ensure that the relative size of the controls on different screens is consistent and looks exactly the same. Take the two adaptation schemes of a great player as an example:

  1. Solution 1: Write a script to convert the length into the length at each resolution. The disadvantage is that it is difficult to cover all resolutions on the market.
  2. Solution 2. AutoLayout support library. The idea of ​​this library is very good: compare the design drawing, use px to write the layout, and it will not affect the preview; during the drawing stage, the px value of the corresponding design drawing will be calculated and converted to the size suitable for the current screen; to simplify the access, each Layout will be automatically converted to the corresponding AutoLayout during inflation, so there is no need to change it in all xml. However, this library also has the following problems:
  • Poor scalability. For each ViewGroup, you need to write the corresponding AutoLayout to expand it, and for each attribute of each View that needs to be adapted, you need to write code to adapt and expand it;

Numerical calculations are performed in the onMeasure phase. This consumes performance, and there are many unreasonable aspects for attributes that are not in LayoutParams. For example, when the textSize of a TextView is converted and set in onMeasure, the textSize that the player has set dynamically in the code will become invalid, because it will be reset and overwritten by AutoLayout every time onMeasure is called.

There are many issues and the author no longer maintains it.

2. Ideas

For screens with large differences in size, the same design solution should not be used, otherwise the advantages of large screens will not be fully reflected. The official adaptation solution seems to express this meaning. However, in actual design and development, for an ordinary App, few projects are willing and energetic to design and develop a set of design solutions for each screen to adapt.

A common simple adaptation requirement is: if the width of the design drawing is 200, and the length of a control marked on the design drawing is 3, then the length of the control is equivalent to 3/200 of the total width. Then we hope that the length of the control on any screen size is 3/200 of the screen width.

I personally think that the design concept of AutoLayout is very good, but the solution of using LayoutParams and attributes as the entry point for conversion calculation in the mesure process has problems in efficiency and scalability. So where is the end of Android's length calculation, and can it be converted when Android calculates the length? If it can be converted when Android calculates the length, then there is no need for a series of redundant calculations and adaptations, and all problems will be solved.

After some searching, I found that the system's length calculation is done by the applyDimension function in TypedValue. The unit and value are passed in to calculate the corresponding px value.

  1. public   static   float applyDimension( int unit, float value,
  2. DisplayMetrics metrics)
  3. {
  4. switch (unit) {
  5. case COMPLEX_UNIT_PX:
  6. return value;
  7. case COMPLEX_UNIT_DIP:
  8. return value * metrics.density;
  9. case COMPLEX_UNIT_SP:
  10. return value * metrics.scaledDensity;
  11. case COMPLEX_UNIT_PT:
  12. return value * metrics.xdpi * (1.0f/72);
  13. case COMPLEX_UNIT_IN:
  14. return value * metrics.xdpi;
  15. case COMPLEX_UNIT_MM:
  16. return value * metrics.xdpi * (1.0f/25.4f);
  17. }
  18. return 0;
  19. }

You can see that the conversion method is very simple, and all properties of DisplayMetrics are public and can be modified without reflection;

The original meaning of pt is the length unit pound. By modifying metrics.xdpi according to the current screen and design drawing size, we can redefine the pt unit into the relative length unit we need, so that the 1pt calculated after the modification actually corresponds to px/screen width px=1px/design drawing width px.

Where does this DisplayMetrics come from? From the source code, we can see that it is generally mContext.getResources().getDisplayMetrics(), and this mContext is the Activity;

Configuration changes such as switching between horizontal and vertical screens will cause DisplayMetrics to be recalculated and restored;

px, dp and sp are all commonly used units, while pt, in and mm are rarely seen. Starting with these uncommon units will not affect other commonly used units.

Based on the above points, the following plan was proposed.

3. Solution

The goal of this adaptation solution is to write the page exactly according to the dimensions marked on the design drawing, so that the written page behaves consistently on screens of all sizes and resolutions, that is, the relative size of the controls relative to the entire screen is consistent on all screens (it looks like the design drawing is just scaled proportionally to the screen width).

Core. Use the unpopular pt as the length unit, and redefine it as a relative unit related to the screen size according to the above idea, which will not affect the use of common units such as dp.

Draw. When writing XML, write it completely according to the size on the design draft, except that the unit is changed to pt. If the width of the design is 200, and the length of a control marked on the design is 3, you only need to define the width as 200 during initialization, and write the length as 3pt when drawing the control. Then, on any screen size, the length of the control will be 3/200 of the screen width. If you need to convert to px dynamically in the code, use TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, value, metrics).

Preview. Drawing the page is an important step in real-time preview. Take the 1334x750 design as an example. In order to achieve the same preview function as normal drawing, create a device with a length of 1334 pounds and a width of 750 pounds as a preview, which is approximately 21.5 inches ((sqrt(1334^2+750^2))/72) after conversion. Just select this device when previewing.

Code processing. Just modify DisplayMetrics in activityonCreate. It is recommended to write it in the base class or ActivityLifecycleCallbacks. Refer to github demo.

  1. Point size = new Point();
  2. activity.getWindowManager().getDefaultDisplay().getSize( size );
  3. context.getResources().getDisplayMetrics().xdpi = size .x / designWidth * 72f;

The page drawn in this way is almost exactly the same as the design drawing, and it looks like the design drawing is scaled up or down no matter the size of the screen.

Before adaptation (left picture API19 400x800, right picture API24 1440x2560):

After adaptation (left picture API19 400x800, right picture API24 1440x2560):

Although the solution is relatively simple, it has been organized into a library for easy use. The code and demo can be found on github.

<<:  Google open sources Swift for TensorFlow: Can we finally put Python aside?

>>:  I only understood this after working for 10 years. If I had known earlier, my position would have been two levels higher than it is now.

Recommend

It took only 9 hours to return to Earth. How come Shenzhou-13 is so fast?

Mixed Knowledge Specially designed to cure confus...

APP promotion and operation: How did the first batch of users come?

When developing an APP, we must first understand ...

Why are the short dramas that are going viral on the Internet so addictive?

Review expert: Chen Mingxin, national second-leve...

Can controlled nuclear fusion become a reality?

We live in an era of technological explosion, wit...

3 tips for high-conversion promotion creativity!

What kind of creative has a high click-through ra...

3 common scenarios for community operations!

First of all, we must make it clear that a commun...

The changes of these two products are worth your attention

On the first day of every week, we will monitor a...

Better than the built-in file manager in Windows 11? Files App

I think everyone is using Windows' file explo...

How to do content marketing on Zhihu?

With the disappearance of the demographic dividen...