Screen adaptation is a pain in the ass when you’re developing Android, and it’s a pain in the ass when it comes to screen sizes. If we change the Angle we look at this problem, I don’t know if you have any knowledge of web front-end development, or you are familiar with the web page, in fact, the problem of adaptation in the design of web pages also exist in theory, why say so? The resolution of the computer monitor, including the phone resolution, I dare say, is far more diverse than the resolution of Android devices, so there is a very strange phenomenon:
Why have Web page designers never said that screen fit is troublesome?
So, what is the reason why web design can still give users a quality experience in a wide range of resolutions? With this doubt, I asked the next front-end friend, who asked me wide-eyed: what is adaptation? The front end does not seem to have this kind of problem, and then after I asked carefully, she told me, oh this size ah, we generally add a viewport, I am set to 20% zoom ~~ to get to the bottom, in fact, is one reason, the web page provides the zoom ratio calculation size.
Similarly, after getting the design drawing given by UI, have you complained that UI sister’s logo is PX, while I use DP in the project, which is what 😂, and UI explanation she does not understand, development is also helpless. Therefore, can there be a perfect solution to solve the conflict between Android engineers and UI sister, to achieve a fixed size of UI design draft, and then you write the layout without thinking, without thinking, copy the above identified pixel value, can achieve perfect fit. The ideal is full, but the reality is cruel:
Due to the openness of Android system, any user, developer, OEM and operator can customize Android, thus resulting in:
-
Fragmentation of Android system: MIUI customized by Xiaomi, Flyme customized by Meizu, EMUI customized by Huawei, etc., of course, they are all customized based on the native system of Google
-
Android models have fragmented screen sizes: 5 “, 5.5 “, 6 “and so on
-
Android screen resolution fragmentation: 320×480, 480×800, 720×1280, 1080×1920
According to umeng Index, as of December 2015, there are 27,796 devices supporting Android
With fragmentation of Android, screen size, and screen density, it’s easy to have the same element appear differently on different phones.
Consider this scenario:
A UI design for a 4.3-inch screen running on a 5.0-inch screen is likely to have a lot of white space on the right and bottom side; The 5.0-inch UI design diagram may not be displayed on a 4.3-inch device.
There are so many kinds of screens, so you need a perfect solution to solve the problem of screen adaptation. Before introducing screen adaptation solutions, let’s briefly introduce some important concepts used in Android screens: **
The screen size
· Meaning: The physical dimensions of the diagonal of the phone
· Unit: Inch, 1 inch =2.54cm
Common Android phone sizes are 5 inches, 5.5 inches, 6 inches and so on
Screen resolution
· Meaning: total pixel points of mobile phone in horizontal and vertical direction
-
Generally described as “width x height” of the screen =AxB
-
Meaning: The screen has A pixels in the horizontal direction (width) and B pixels in the vertical direction (height)
Example: 1080×1920, 1080 pixels in width and 1920 pixels in height
- Unit: px (Pixel), 1px=1 pixel point
UI designers will use PX as a unified unit of measurement in their drawings
- Common Android phone resolutions: 320×480, 480×800, 720×1280, 1080×1920, 1080×2340
Screen pixel density
-
Meaning: Points in pixels per inch
-
Unit: Dpi (dots per ich)
Assuming 160 pixels per inch inside the device, the screen pixel density of the device =160dpi
- Android phones have a corresponding screen pixel density for each type of phone screen size:
The density of the type | Represents the resolution (PX) | Screen Density (DPI) |
---|---|---|
Low density (LDPI) | 240×320 | 120 |
Medium density (MDPI) | 320×480 | 160 |
High density (HDPI) | 480×800 | 240 |
Ultra High Density (XHDPI) | 720×1280 | 320 |
Ultra High Density (XXHDPI) | 1080×1920 | 480 |
The relationship between screen size, resolution and pixel density
The resolution of a mobile phone is width * height, and the screen size is in inches, so the relationship between the three is:
It doesn’t matter if you don’t understand. Here’s an example
Suppose a mobile phone has a resolution of 1080×1920 (px) and a screen size of 5 inches. What is the density?
Solution: Please apply the formula directly
Density-independent pixel
- Density -independent pixel, called DP or DIP, is independent of the actual physical pixels on the terminal.
- Unit: DP, which can ensure the same effect on devices with different screen pixel densities
- Android development uses dp instead of PX units to set the image size, which is Android specific
- Scenario: If both draw a line half the length of the screen, if px is used as the unit of measurement, set it to 240px on the 480×800 resolution phone; On a 320×480 phone it should be 160px, but the Settings are different. If you use dp as a unit, 160DP is displayed as half the length of the screen at both resolutions.
- Conversion of DP to PX
Since the UI designer gives you a design in px units and Android development uses DP units, we need to convert:
The density of the type | Represents the resolution (PX) | Screen Density (DPI) | Conversion (PX/DP) |
---|---|---|---|
Low density (LDPI) | 240×320 | 120 | 1 dp = 0.75 px |
Medium density (MDPI) | 320×480 | 160 | 1dp=1px |
High density (HDPI) | 480×800 | 240 | 1 dp = 1.5 px |
Ultra High Density (XHDPI) | 720×1280 | 320 | 1dp=2px |
Ultra High Density (XXHDPI) | 1080×1920 | 480 | 1dp=3px |
In Android, it is defined as 160dpi (320×480 screen resolution) : 1dp=1px
Independent proportional pixel
- Scale-independent Pixel is sp or SIP
- Unit: sp
Android development uses this unit to set text sizes, which can be scaled according to font size preferences.
12SP, 14sp, 18sp and 22sp are recommended as font sizes. Odd numbers and decimals are not recommended, which may cause loss of accuracy. Fonts less than 12sp are too small for the user to see
Keep the above concepts in mind, as they will be used throughout the rest of this tutorial!
Comparison of adaptation schemes
1. Dp native scheme
2. Dimen adaption based on PX and DP (width and height qualifier and smallestWidth adaption)
3. Headline screen adaptation scheme
4. Improved version of headline adaptation scheme
Dp native scheme
Preface: What’s the problem with px as the unit?
Android screen adaptation has a long history, the key is that screen size and screen resolution vary greatly, and many UI engineers in order to accommodate iOS and Android adaptation, resulting in the design of UI draft marked in PX units. In the face of hundreds of models, px units have been difficult to adapt.
1. Same size, different resolutions:
A 1080px width showing 100px ratio is 100/1080
The 720px width shows 100px with a ratio of 100/720
2. Same resolution, different sizes:
1080px displays 100px on 4.7 inches
1080px displays 100px on 6.1 inches
If you use more than one set of PX file scheme to match, the market less said hundreds of inches, the need for too many files.
How do screens of different resolutions fit
At this point, dp solution is needed to solve, so what problem does DP solve?
The following formula shows that the number of pixels per 1DP is different for devices of the same size with different resolutions (density).
480 dpi 1dp = 1 * 3 = 3px
1dp = 1 * 2 = 2px on 320 dpi
240 dpi 1dp = 1 * 1.5 = 1.5px
160 dpi 1dp = 1 * 1 = 1px
1dp = 1 * 0.75 = 0.75px on 120 dpi
But the physical length represented (160dp=1in) is the same.
The density=3 represents 480px and the physical length is 1 in
Density =2; the physical length is 1 in
The density of dp is 240px and the physical length is 1 in
Density =1; the physical length is 1 in
The density=0.75 represents 120px and the physical length is 1 in
The use of dp units means that you will see the same size on devices of the same size but with different resolutions, and the proportions will be the same across devices.
What problem does dp solution not solve
Here’s an example:
Screen resolution: 1920*1080, screen size 5 “, then dPI 440. Suppose our UI design was designed with a screen width of 360DP, what would be the problem with that?
On the above device, the screen width is actually 1080/(440/160)=392.7dp, which means the screen is wider than the design drawing. In this case, even using DP will not display the same effect on different devices. At the same time, the screen width of some devices is less than 360DP, which will lead to the actual display of incomplete development based on 360DP width.
Moreover, the above relationship between screen size, resolution and pixel density is not realized by many devices according to this rule, so the VALUE of DPI is very disorderly and there is no rule to follow, resulting in unsatisfactory adaptation effect of DP.
Dimen adaption based on PX and DP (width and height qualifier and smallestWidth adaption)
Dimen ADAPTS the SmallestWidth qualifier based on DP
Principle:
This fit is based on the minimum width qualifier. Android will recognize the minimum dp size of the available height and width of the screen (in fact, the width of the phone) and then go to the resource file to find the resource file under the corresponding qualifier folder. This mechanism is the same as the width and height qualifier adaptation mentioned above, in that the system selects corresponding files according to specific rules.
For example, the DPI of Mi 5 is 480, and the horizontal pixel is 1080px. According to px=dp(DPI /160), the horizontal DP value is 1080/(480/160), i.e. 360DP, the system will look for whether there is a folder of value- SW360DP and corresponding resource files.
The difference between smallestWidth qualifier adaptation and width and height qualifier adaptation is that it has a very good fault tolerance mechanism. If there is no value-SW360DP folder, the system will look down, for example, the nearest to the 360DP folder is only value-SW350DP. Android then selects the resource file under the value- SW350DP folder. This feature perfectly solves the problem of tolerance for width and height qualifiers mentioned above.
Disadvantages:
- Invasive strong
- Android customized, uneven width, not all phones.
- There are N new folders in the project, and it is very inconvenient to pull up and down files: to see string or color resource files, you need to drag a lot to get to them.
- By using the proximity principle of the width qualifier, you can see that the size of the match is not accurate enough.
- It was introduced after Android 3.2, and Google intended to use it for tablet layout files (although it works better for Diemns), but it doesn’t really matter that all SPX projects currently support 5.1 at the minimum.
Dimens ADAPTS width and height qualifiers based on PX
Principle:
Based on the analysis of the proportion of mobile phone resolutions in the market, we selected one with a high proportion (such as 1280*720) as a benchmark, and then other resolutions were adapted according to this benchmark.
Reference means (e.g. 320*480 resolution as reference) :
The width is 320, and the width of any resolution is divided into 320 parts, ranging from x1 to x320
The length is 480, and the height of any resolution is divided into 480 parts, with values from Y1 to Y480
For example, for 800 * 480 resolution devices, you need to set the following in the dimens. XML file in the values-800×480 directory of the project (which can be automatically generated by the tool, of course) :
<resources> <dimen name="x1">1.5px</dimen> <dimen name="x2">3.0px</dimen> <dimen name="x3">4.5px</dimen> <dimen Name = 6.0 px "x4" > < / dimen > < dimen name = "x5" > 7.5 px < / dimen > < / pre >Copy the code
You can see that x1 = 480 / baseline = 480/320 = 1.5; It means the same 1px, 1px on a 320/480 phone and 1×1.5px on a 480/800 phone, and the px will automatically fit according to the different values folders we specify.
Verification scheme:
Simply verify whether this scheme can achieve the effect of adaptation through calculation. For example, there is a 187DP wide View on the design drawing.
The resolution is 480 x 800
- Width ratio of design drawing: 187DP / 375DP = 0.498
- The actual width ratio at 480 800 = 187 1.28px / 480 = 0.498
The resolution is 1080 x 1920
- Width ratio of design drawing: 187DP / 375DP = 0.498
- Actual width ratio at 1080 1920 = 187 2.88px / 1080 = 0.498
- Calculation height same
Disadvantages:
- Invasive strong
- The resource file needs to be accurately matched to fit, for example, 1920×1080 phones must find the 1920×1080 qualifier, otherwise the default dimens file will be uniform. With the default size, the UI is likely to be distorted or, in short, poorly fault-tolerant.
- Android phones with different resolutions are too many, you may say that the mainstream can, indeed small companies can mainstream, Taobao App certainly can not only adapt to mainstream mobile phones. The size of the controls on the design and the gaps between them are very different on small and large phones, and you’ll find that the controls on large phones are extremely large. You might think it’s normal, because the resolution is different. But the actual effect is exaggerated.
- Occupy large resources: hundreds of kilobytes, even up to 1M or more.
Headline screen adaptation solution
Grooming needs:
First of all, let’s sort out our requirements. Generally, our design drawings are designed with fixed sizes. For example, if the screen is designed with a resolution of 1920px by 1080px and density is 3, the screen is actually 640DP by 360DP. If we want to display all the same on all the devices, it is not practical because the aspect ratio of the screen is not fixed, 16:9, 4:3, and other aspect ratios constantly appear, so it is impossible to display all the same. But usually, we only need a dimension to width or height to fit, for example, we Feed is sliding up and down, just make sure according to eye to eye on all of the dimensions of equipment in the wide, such as another does not support the sliding up and down the page, you need to ensure they show in the high dimension, especially not shown on some equipment is not complete. At the same time, considering that the current adaptation is based on DP, if the new scheme does not support DP, the cost of migration will be very high.
Therefore, the general requirements are summarized as follows:
- The width or height of a dimension is compatible with the design drawing.
- Support dp and SP units to minimize migration costs.
Find a solution compatible breakthrough
The formula for converting from DP to PX:
As you can see, if the design is 360dp wide, we have to change the density value to ensure that the px values calculated on all devices are exactly the screen width. Density is a member variable of DisplayMetrics, and DisplayMetrics instances are available via Resources#getDisplayMetrics, Resouces are obtained from the Activity or Application Context.
Let’s get familiar with a few variables related to DisplayMetrics neutralization and adaptation:
- DisplayMetrics#density is the density described above
- DisplayMetrics#densityDpi is the dpi above
- DisplayMetrics#scaledDensity specifies the scale factor of a font. Normally, it is the same as density, but adjusting the system font size will change this value
Are all dp and PX conversions in Android calculated using relevant values in DisplayMetrics?
- We’ll start by looking at the dp conversions in the layout file and end up calling TypedValue#applyDimension to do the conversions
- Decode images, BitmapFactory#decodeResourceStream methods:
Of course, there are other DP transformation scenarios, which are basically calculated by DisplayMetrics, and I won’t go into detail here. Therefore, to meet the above requirements, we only need to modify the variables related to DisplayMetrics and DP transformation.
Final plan:
Let’s assume that the width of the design is 360DP, and the wide dimension fits.
Then customize the density = the real width of the device (unit: px) / 360 after adaptation. Then we just need to modify the calculated density in the system. The code is as follows:
Also called in the Activity#onCreate method. The code is relatively simple and does not involve the invocation of the system’s non-public API, so theoretically it will not affect the stability of APP.
Disadvantages:
- Only one of the height or width can be used as the reference for adaptation.
- Only need to modify density once, 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, you can only adapt the whole project with one knife, but the adaptation scope is not controllable. If system controls, tripartite library controls and other controls that are not designed by the project itself are used in the project, there will be a very large gap between the size of the design drawing and that of the project itself.
Headline adaptation solution improved version
Based on the header adaptation scheme, rewrite the Activity getResources() as the baseline unit, which is a unit of length in Android: Represents a dot and is the physical size of the screen, which is 1/72 of an inch, or 72pt equals an inch
- AdaptScreenUtils
public final class AdaptScreenUtils { private static List<Field> sMetricsFields; private AdaptScreenUtils() { throw new UnsupportedOperationException("u can't instantiate me..." ); } /** * Adapt for the horizontal screen, and call it in {@link android.app.Activity#getResources()}. */ public static Resources adaptWidth(final Resources resources, final int designWidth) { float newXdpi = (resources.getDisplayMetrics().widthPixels * 72f) / designWidth; applyDisplayMetrics(resources, newXdpi); return resources; } /** * Adapt for the vertical screen, and call it in {@link android.app.Activity#getResources()}. */ public static Resources adaptHeight(final Resources resources, final int designHeight) { return adaptHeight(resources, designHeight, false); } /** * Adapt for the vertical screen, and call it in {@link android.app.Activity#getResources()}. */ public static Resources adaptHeight(final Resources resources, final int designHeight, final boolean includeNavBar) { float screenHeight = (resources.getDisplayMetrics().heightPixels + (includeNavBar ? getNavBarHeight(resources) : 0)) * 72f; float newXdpi = screenHeight / designHeight; applyDisplayMetrics(resources, newXdpi); return resources; } private static int getNavBarHeight(final Resources resources) { int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId ! = 0) { return resources.getDimensionPixelSize(resourceId); } else { return 0; } } /** * @param resources The resources. * @return the resource */ public static Resources closeAdapt(final Resources resources) { float newXdpi = Resources.getSystem().getDisplayMetrics().density * 72f; applyDisplayMetrics(resources, newXdpi); return resources; } /** * Value of pt to value of px. * * @param ptValue The value of pt. * @return value of px */ public static int pt2Px(final float ptValue) { DisplayMetrics metrics = FWAdSDK.sContext.getResources().getDisplayMetrics(); Return (int) (ptValue * metrics. Xdpi / 72f + 0.5); } /** * Value of px to value of pt. * * @param pxValue The value of px. * @return value of pt */ public static int px2Pt(final float pxValue) { DisplayMetrics metrics = FWAdSDK.sContext.getResources().getDisplayMetrics(); Return (int) (pxValue * 72 / metrics. Xdpi + 0.5); } private static void applyDisplayMetrics(final Resources resources, final float newXdpi) { resources.getDisplayMetrics().xdpi = newXdpi; FWAdSDK.sContext.getResources().getDisplayMetrics().xdpi = newXdpi; applyOtherDisplayMetrics(resources, newXdpi); } static void preLoad() { applyDisplayMetrics(Resources.getSystem(), Resources.getSystem().getDisplayMetrics().xdpi); } private static void applyOtherDisplayMetrics(final Resources resources, final float newXdpi) { if (sMetricsFields == null) { sMetricsFields = new ArrayList<>(); Class resCls = resources.getClass(); Field[] declaredFields = resCls.getDeclaredFields(); while (declaredFields ! = null && declaredFields.length > 0) { for (Field field : declaredFields) { if (field.getType().isAssignableFrom(DisplayMetrics.class)) { field.setAccessible(true); DisplayMetrics tmpDm = getMetricsFromField(resources, field); if (tmpDm ! = null) { sMetricsFields.add(field); tmpDm.xdpi = newXdpi; } } } resCls = resCls.getSuperclass(); if (resCls ! = null) { declaredFields = resCls.getDeclaredFields(); } else { break; } } } else { applyMetricsFields(resources, newXdpi); } } private static void applyMetricsFields(final Resources resources, final float newXdpi) { for (Field metricsField : sMetricsFields) { try { DisplayMetrics dm = (DisplayMetrics) metricsField.get(resources); if (dm ! = null) dm.xdpi = newXdpi; } catch (Exception e) { Log.e("AdaptScreenUtils", "applyMetricsFields: " + e); } } } private static DisplayMetrics getMetricsFromField(final Resources resources, final Field field) { try { return (DisplayMetrics) field.get(resources); } catch (Exception e) { Log.e("AdaptScreenUtils", "getMetricsFromField: " + e); return null; }}}Copy the code
- Method of use
Width 320 as the benchmark for adaptation
@Override
public Resources getResources() {
return AdaptScreenUtils.adaptWidth(super.getResources(),320);
}
Copy the code
Suppose I now need a button in the center of the screen that is 1/2 the width and height of our screen, how can I write a layout file?
<FrameLayout>
<Button
android:layout_gravity="center"
android:gravity="center"
android:text="@string/hello_world"
android:layout_width="160pt"
android:layout_height="160pt"/>
</FrameLayout>
Copy the code
The effect
480 x 800 – mdpi(160dpi)
720 x 1280 – xhdpi(320dpi)
1080 x 1920 – xxhdpi(480dpi)
It can be seen that the WebView in the effect diagram does not produce the problem of adaptation failure for the later View, which is the problem that the previous adaptation can not solve.
advantages
1. No invasive The still can use dp after this includes any other units, the layout will not cause any influence to the formerly used to develop new functions in old projects you can boldly to join the adaptation scheme, a new project can not hesitate to use the adapter, and, after close the pt effect is equal to dp.
2. High flexibility if you want to make a View with different resolution devices, so that the size of the adaptive dimension of the same proportion, then use PT units for it, if you do not want this effect, but want to display more content on a larger device, You can write dp and SP as you did before, and combine these two things and you have a lot of flexibility in the layout of the interface.
3. It will not affect the size of the system View and the three-party View, which has been shown in non-invasive mode. The solution of toutiao is to directly modify the dp adaptation of DisplayMetrics#density, which will cause the size of the system View to be inconsistent with the original. For example, Dialog, Toast, size, also, the size of the three-party View will be inconsistent with the original effect, which is one of the reasons for choosing PT adaptation.
4. It will not fail because no matter the headline adaptation or other three-party library adaptation, DisplayMetrics#density will be restored and needs to be reset. The most significant is the presence of WebView in the interface. There is a solution for this, of course, but there are many other cases where the DisplayMetrics#density value will be restored and the adaptation will fail. My solution is to solve this pain point, so that the value of DisplayMetrics is not restored and the adaptation fails.
Disadvantages:
Can only be adapted to one side of the width or height, but this is also the pain point of most adaptation schemes, length and width can only be adapted to one of them, but most companies in the use of these schemes to adapt is the first adaptation wide, and then in the long sliding form to solve;
Summary:
Although the dimen adaption scheme based on PX and DP can cover the screen adaption of all models in the market, the redundant DImen files will make engineers live in death, and this scheme is very intrusive, once used, it will make it very difficult to reverse; As a non-invasive way to access, the headline adaptation scheme and the headline adaptation optimization scheme can perfectly solve the problem of code redundancy. Moreover, the overall scheme has high flexibility, but only wide or high can be selected as the only dimension for adaptation.
All of the above solutions can be used to solve the screen adaptation problem. Each solution has its own unique advantages and disadvantages, so the final choice will vary from person to person
Reference article:
Android screen adaptation and solutions
Android Screen Adaptation: The most comprehensive solution
Android screen adaptation solution
A very low cost Android screen adaptation
Android heard you’re still using DP units for screen adaptation?
❤️ Thank you
That is all the content of this sharing. I hope it will help you
Don’t forget to share, like and bookmark your favorite things.
Welcome to pay attention to the public number programmer bus, an interesting, stylish, temperature programmer bus, dabin dachang face, programmer life, actual combat tutorials, technology and other content, pay attention to me, make a friend.