1. Overview
The Android fragmentation problem is a nightmare for every developer, and this article summarizes the Android adaptation issue in a comprehensive way.
First of all, look at the official report released by Google August 1, 2016:
Relative numbers of devices related to the Android platform version:
You can see that the 4.1 version and above are 96%, so the adaptation priority is more than 4.1 version adaptation issues.
The screen configuration is defined by screen size and density for devices with specific screen configurations:
From the statistical data can be seen, hdpi, xhdpi and xxhdpi share reached 95%.
Detailed statistics see here:
Https://developer.android.com/about/dashboards/index.html#Platform
Adapting to official statistics is the first step in getting started.
2. Key Concepts
Screen size, screen resolution, screen pixel density
Screen Size: screen size refers to the diagonal length of the screen, in inches, 1 inches = 2.54 centimeters, such as common Android phone sizes, 5.0, 5.5 inches.
screen Resolution: The screen resolution refers to the number of pixels in the vertical direction, in px,1px=1 pixels. Generally in portrait pixels * transverse pixels, such as 1960*1080.
screen pixel density: the screen pixel density refers to the number of pixels per inch, in DPI, the abbreviation for dot per inch. Screen pixel density is related to screen size and screen resolution, in the case of single change, the smaller the screen size, the higher the resolution, the greater the pixel density, the lower the inverse.
PX, dip, DP, DPI, SP
px: The front resolution is in pixels, in most cases, such as UI design, Android native API will use PX as a unified unit of measurement, such as to obtain a higher screen width.
*dip and Dp:**dip and DP is a meaning, are density independent pixels abbreviation, that is, density-independent pixels, as we said above, DPI is the screen pixel density, if there is 160 pixels in an inch, This screen pixel density is 160dpi, then in this case, the DP and PX How to convert it? In Android, the rule is 160dpi, 1dip=1px, if the density is 320dpi, then 1dip=2px, and so on. Conversion formula: PX = DP (dpi/160).
Note: If the parameter of a device is 480x320,160dpi,b, the parameter set is 800x480,240dpi. We want to draw a line as long as the width of the screen, if using PX as a unit, must be set to 320px on the a device, set 480px on the B device. But if we use DP as the unit, because the 1dp=1px is based on 160dpi, a device set to 320DP is equal to the screen width (320px), the B device is set to 320DP is equal to 320x (240/160) =480px, that is, the screen width of the B device. In this way, a simple screen fit can be achieved using DP as a unit. This knowledge is a coincidence, also has the B device pixel density is not so just good, we need to use other screen adaptation technology. This solves different screen resolution problems, but does not solve the screen physical size problem.
**sp:**scale-independent pixels abbreviations, which can be scaled automatically based on the text size preference. Google recommends that we use more than 12sp of size, usually can use 12SP,14SP,18SP,22SP, it is best not to use odd and decimal.
MDPI, hdpi, xhdpi, xxhdpi, xxxhdpi
MDPI, hdpi, xhdpi, xxhdpi are used to modify the Drawable folder and the values folder in Android to distinguish between images and dimen values in different pixel densities.
When designing icons, the five main pixel densities (MDPI, HDPI, XHDPI, xxhdpi, and xxxhdpi) should be scaled according to the 2:3:4:6:8 scale. For example, the size of a boot icon is 48x48 DP, which means that on MDPI's screen its actual size should be 48x48 px, its actual size on the HDPI screen is 1.5 times times MDPI (72x72 px), and its actual size on the XHDPI screen is MDPI 2 Times (96x96 px), and so on.
3. Resolving the problem of resolution fragmentation
(1) using the dip (Density independent pixels abbreviation, i.e., density-independent pixels)
Because the pixel densities of various screens are different, the actual size of the same number of pixels on different devices also varies, so using pixels to define layout dimensions creates problems. Therefore, be sure to specify the dimensions using DP or SP units. DP is a non-density-restricted pixel whose size is the same as the actual size of the pixel at which it is being dpi. SP is also a basic unit, but it can be adjusted according to the user's preferred text size (that is, scale independent pixels), so we should use that unit of measure to define the text size.
Note:
Although DP can remove the problem of different pixel density, so that the 1DP in different pixel density on the same display, but still due to the diversity of Android screen devices, if using DP as a unit of measure, not all the width of the screen is the same DP length, for example, the Nexus S and Nexus One belong to hdpi, the screen width is 320DP, and the Nexus 5 belongs to xxhdpi, the screen width is 360dp,galaxy Nexus belongs to xhdpi, the screen width is 384dp,nexus 6 belongs to xxxhdpi, The screen width is 410DP. So, the light of Google's own products there are already so many standards, and screen width and pixel density does not have any correlation, even if we use DP, 320DP width of the device and 410DP devices, there will be 90DP differences. Of course, we try to use match_parent and wrap_content, as little as possible with the DP to specify the specific length of the control, and then combined with the weight, most of the situation we can do to fit.
(2) provide alternate bitmap
Since Android can run on devices with a variety of screen densities, the bitmap resources we provide should always meet the requirements for a wide range of density ranges: low density, medium density, high density, and ultra high density. This will help our pictures to achieve excellent quality and effect on all screen densities.
To generate these images, we should first extract the original resources in vector format and then generate the corresponding images for each density according to the following size ranges.
xxxhdpi:4.0
xxhdpi:3.0
xhdpi:2.0
hdpi:1.5
mdpi:1.0 (minimum requirement)
ldpi:0.75
That is, if we generate images of 200x200 px size for xhdpi devices, we should use the same resource to generate images of ldpi, 150x150, and 100x100 sizes for hdpi, mdpi, and 75x75 devices.
Then, place the resulting picture file in the appropriate subdirectory under res/(MDPI, hdpi, xhdpi, xxhdpi), and the system will automatically select the appropriate image based on the screen density of the device running your app.
This way, as long as we reference @drawable/ID, the system can select the appropriate bitmap based on the DPI of the screen.
But there is one more question to note, if it is. 9 picture or do not need more than the resolution of the image, put in the Drawable folder, the corresponding resolution of the picture should be placed correctly in the appropriate folder, otherwise it will cause problems such as picture stretching.
4. To solve the different sizes of equipment above the adaptation
(1) using wrap_content, match_parent, weight
To ensure the flexibility of the layout and to accommodate screens of various sizes, you should use "Wrap_content" and "match_parent" to control the width and height of some view components.
With "Wrap_content", the width or height of the view is set to the minimum size required to fit the content in the view, and "Match_parent" is called "fill_parent" at levels below the API level 8 ) expands the component to match the dimensions of its parent view.
If you use the "Wrap_content" and "match_parent" dimension values instead of the hard-coded dimensions, the view will use only the space or expansion that you want to fill the available space accordingly. This method allows the layout to properly accommodate various screen sizes and screen orientations.
Weight is a unique property of linear layouts, and we can use this property to distribute the interface in proportion to achieve some special requirements.
We set the layout in a linear layout, horizontal arrangement, and then placed two width of 0dp buttons, set weight to 1 and 2, respectively, we can see two buttons according to the width of the 1:2 of the normal arrangement, which is also our frequent use of the scene, it is very good to understand.
If our width is not 0DP (Wrap_content and 0DP have the same effect), then is it match_parent?
In this case, the ratio is exactly the opposite of the above (2:1), what's going on? Speaking of which, we have to mention the calculation method of weight.
The true meaning of android:layout_weight is that if the view is set to this property and is valid, then the width of the view is equal to the original width (android:layout_width) plus the percentage of the remaining space.
From this angle, let's explain the above phenomenon. In the above code, we set the width of each button is match_parent, assuming that the screen width is L, then each button should be the width of L, the remaining width is equal to L (l+l) =-L.
Button1 Weight=1, the remaining width of the ratio is 1/(1+2) = 1/3, so the final width is l+1/3* (-l) =2/3l,button2 the calculation is similar to the final width of L+2/3 (-L) =1/3l.
The vertical direction is the same.
(2) Use relative layout to disable absolute layout
In development, we use linear layouts, relative layouts, and frame layouts most of the time, and the absolute layout is rarely used because of the poor fit.
Because of the different layout features are different, so you can not say which layout is good, in the end should use what layout can only be determined according to actual needs. We can use nested instances of linearlayout and combine "wrap_content" and "match_parent" to build a fairly complex layout. However, we cannot precisely control the special relationship of the sub-view through LinearLayout, and the system will list the views in linearlayout directly
If we need to arrange the sub-views in various effects instead of a straight line, it is often more appropriate to use relativelayout so that the layout can be specified based on the special relationship between the components. For example, we can snap a child view to the left side of the screen while aligning another view to the right side of the screen.
(3) Using auto-stretch bitmap
Supporting a variety of screen sizes often means that your picture resources must also be adaptable to a variety of sizes. For example, the button background must be adaptable regardless of the button to which the shape is to be applied.
If you use a simple picture on a component that can change the size, you will soon find that the display is somewhat less than ideal, as the system will stretch or shrink your picture evenly at run time. The workaround is to use an auto-stretch bitmap, which is a special format for the PNG file, which indicates which areas can be stretched and cannot be stretched.
.9 of the production, is actually the original image to add the 1px boundary, and then according to our needs, the corresponding position is set to black line, the system will be based on our actual needs to stretch.
(4) matching of text and size
We need to run the code in a 1920*1200 resolution 320DPI tablet, found that all the fonts have become larger, seemingly 1920*1200 resolution than the previous 1280*800 to a large circle, but because the DPI is also high, so the font becomes larger.
After running the above fetch smallestscreenwidth code, the discovery value is 600. (The value of the base size tablet is 800)
First create a Dimens.xml file in the values folder:
Continue to establish in RES and the values folder with the same level of two folders Values-sw600dp-land and Values-sw800dp-land, in order to accommodate more screens, also joined the Values-sw480dp-land ( Suffix is land because the project of the example is flat)
Then we each one of the original layout file to find out, find the original written dead "number", such as width and font size, generally speaking unit is DP or SP, these numbers are all in values/ Dimens.xml defines a variable that writes back to the corresponding number in the layout file at the same time.
Then you multiply the dimens.xml inside the Values-sw600dp-land by 0.75来: (because 600/800 equals 0.75)
The Values-sw800dp-land remains the same as the values inside because it is base size.
After this, we run the code to the 1920*1200 resolution 320DPI tablet, found that this time the font space and height are the same as the original base size, like it is running in the base size flat on the feeling!
Automatic generation of Dimens tool classes:
Public class dimentool { Public Static void Gen() {File File =NewFile ("./app/src/main/res/values/dimens.xml"); BufferedReader reader =NULL; StringBuilder sw480 =NewStringBuilder (); StringBuilder sw600 =NewStringBuilder (); StringBuilder sw720 =NewStringBuilder (); StringBuilder sw800 =NewStringBuilder (); StringBuilder w820 =NewStringBuilder ();Try{System.out.println ("Generate different resolutions:"); Reader =NewBufferedReader (NewFileReader (file)); String tempstring;intline =1;//read one line at a time until the end of the file is read in null while((tempstring = Reader.readline ())! =NULL) {if(Tempstring.contains ("</dimen>")) {//tempstring = Tempstring.replaceall ("", "");String start = tempstring.substring (0, Tempstring.indexof (">") +1); String end = Tempstring.substring (Tempstring.lastindexof ("<") -2);intnum = integer.valueof (tempstring.substring (Tempstring.indexof (">") +1, Tempstring.indexof ("</dimen>") -2)); Sw480.append (Start). Append (int) Math.Round (NUM *0.6). Append (end). Append ("\ n"); Sw600.append (Start). Append (int) Math.Round (NUM *0.75). Append (end). Append ("\ n"); Sw720.append (Start). Append (int) Math.Round (NUM *0.9). Append (end). Append ("\ n"); Sw800.append (tempstring). Append ("\ n"); W820.append (tempstring). Append ("\ n"); }Else{sw480.append (tempstring). Append ("\ n"); Sw600.append (tempstring). Append ("\ n"); Sw720.append (tempstring). Append ("\ n"); Sw800.append (tempstring). Append ("\ n"); W820.append (tempstring). Append ("\ n"); } line++; } reader.close (); System.out.println ("<!--sw480 --"); System.out.println (sw480); System.out.println ("<!--sw600 --"); System.out.println (sw600); System.out.println ("<!--sw720 --"); System.out.println (sw720); System.out.println ("<!--sw800 --"); System.out.println (sw800); String Sw480file ="./app/src/main/res/values-sw480dp-land/dimens.xml"; String Sw600file ="./app/src/main/res/values-sw600dp-land/dimens.xml"; String Sw720file ="./app/src/main/res/values-sw720dp-land/dimens.xml"; String Sw800file ="./app/src/main/res/values-sw800dp-land/dimens.xml"; String W820file ="./app/src/main/res/values-w820dp/dimens.xml"; WriteFile (Sw480file, sw480.tostring ()); WriteFile (Sw600file, sw600.tostring ()); WriteFile (Sw720file, sw720.tostring ()); WriteFile (Sw800file, sw800.tostring ()); WriteFile (W820file, w820.tostring ()); }Catch(IOException e) {E.printstacktrace (); }finally{if(Reader! =NULL) {Try{Reader.close (); }Catch(IOException E1) {E1.printstacktrace (); } } } } Public Static void WriteFile(string file, string text) {PrintWriter out =NULL;Try{out =NewPrintWriter (NewBufferedWriter (NewFileWriter (file)); Out.println (text); }Catch(IOException e) {E.printstacktrace (); } out.close (); } Public Static void Main(string[] args) {Gen (); }}
The next article will give Google a percentage of the official support for the way the layout of the Open Source Library: Https://github.com/JulienGenoud/android-percent-support-lib-sample.
Android Screen Adapter Solution