Reprint Please specify source: http://blog.csdn.net/guolin_blog/article/details/50727753
Seems to have a long time not updated blog, I recently in order to prepare the next series of blog, but also spent a long time to study the source code. Unfortunately, the next series of blogs I may have to write for a while, then in order not to let everyone wait too long, today to update a single article, talk about Android drawable micro-skills.
The word micro-skill is also my own invention, because drawable this thing believe that everyone is in use every day, everyone is familiar with it, the reason is called micro-skill is for this we are familiar with the technology, there may be some you do not know the details, Let's explore these tiny details today.
As we all know, in the Android project, the Drawable folder is used to place the image resources, whether it is JPG, PNG, or 9.png, can be placed here. In addition, there are XML files like selector that can be placed under the Drawable folder.
But if you're using Android studio to create a new project, you'll find the following directory structure:
Well? How there are so many mipmap start folder, and their naming rules and Drawable folder is very similar, but also hdpi, MDPI, xhdpi and so on, and the inside is really put pictures, is not the location of the image placed in the Android project has changed?
Developers who have just moved from Eclipse to Android studio may be unfamiliar with the Mipmap folder, but don't worry, our usual programming habits don't need to change because the Mipmap folder is just the icon for the app, that's all. Before this, we are the application icon icon and ordinary picture resources together into the Drawable folder, so it will look messy, and sometimes want to from a bunch of picture resources inside to find icon half a day can not find, and documents more prone to leakage of the situation, But precisely Android is extremely recommended that we put a corresponding size icon under each resolution folder, so separate them out specifically into the Mimap folder is a good solution to this problem.
In addition, placing the icon in the Mipmap folder also allows the launcher icon of our program to automatically have the ability to display cross-device density, For example, a device with a screen density of xxhdpi can automatically load icon under MIPMAP-XXXHDPI as the application's launcher icons, which will look more delicate.
You can refer to this article for the suggested use of mipmap: Getting Your Apps ready for Nexus 6 and Nexus 9, of course you still have to science online.
In addition, for each density of the icon should be designed to what size in fact, Android also gives the best advice, the size of the icon is best not to design, because too low resolution will cause the icon blur, and the high resolution will only increase the APK size. The recommended dimensions are shown in the following table:
density |
Recommended Size |
mipmap-mdpi |
48 * 48 |
mipmap-hdpi |
72 * 72 |
mipmap-xhdpi |
96 * 96 |
mipmap-xxhdpi |
144 * 144 |
mipmap-xxxhdpi |
192 * 192 |
Then we refer to mipmap in a way that is identical to the way we used to refer to drawable, using @mipmap/res_id in our resources, and using r.mipmap.res_id in our code. For example, in Androidmanifest.xml, this refers to the Ic_launcher icon:
<applicationandroid:allowbackup="true"android:icon="@mipmap/ic_ Launcher "android:label=" @string/app_name "android:supportsrtl=" true " android:theme="@style/apptheme"> <activity android:name=". Mainactivity "> <intent-filter> <action android:name="Android.intent.action.MAIN"/> <category android:name="Android.intent.category.LAUNCHER"/> </intent-filter> </activity></Application>
OK, so much about Mimap, it's not the focus of this article, and then we're really looking at some of drawable's micro-tricks.
First I prepared a picture of 270*480 pixels:
Name the picture android_logo.png, and then put it under the Drawable-xxhdpi folder. Why do you put it in this folder? Because the density of my phone's screen is xxhdpi. So how do you know the density of your phone's screen? You can use the following method to get the DPI value to the screen first:
float xdpi = getResources().getDisplayMetrics().xdpi;float ydpi = getResources().getDisplayMetrics().ydpi;
Where xdpi represents the screen width of the DPI value, ydpi represents the screen height of the API value, usually these two values are nearly equal or very close, on my phone these two values are approximately equal to 403. So what does 403 mean? We can see the following table directly:
DPI Range |
density |
0DPI ~ 120dpi |
ldpi |
120DPI ~ 160dpi |
mdpi |
160DPI ~ 240dpi |
hdpi |
240DPI ~ 320dpi |
xhdpi |
320DPI ~ 480dpi |
xxhdpi |
480DPI ~ 640dpi |
xxxhdpi |
As can be seen from the table, the 403dpi is in the range of 320dpi to 480dpi and therefore belongs to the xxhdpi.
After the picture has been placed, I'll refer to this image in the layout file as follows:
<?xml version= "1.0" encoding= "Utf-8"?><linearlayoutxmlns:android="Http://schemas.android.com/apk/res/android" Android:layout_width="Match_parent"android:layout_height="Match_parent" > <ImageViewandroid:id= "@+id/image"android:layout_width="Wrap_ Content "android:layout_height="wrap_content "android:src=" @drawable/android _logo " /> </linearlayout>
Specify the load Android_logo in the ImageView control and set the width of the ImageView control to wrap_content so that the size of the image will be as large as our control.
Now run the program, the effect is as follows:
Because my phone resolution is 1080*1920 pixels, and the resolution of this picture is 270*480 pixels, just one-fourth of the resolution of the phone, so it can be seen that the width and height of the Android_logo picture is about One-fourth of the width of the screen, The size is basically more accurate.
So far everything has been going well, hasn't it? Now let's try to make some changes, and we'll android_ Logo.png This picture moves to the drawable-xhdpi folder, note that you are not copying a copy to the drawable-xhdpi folder, but instead move the picture to the Drawable-xhdpi folder, and then run the program again, as shown in the results:
Well? How does it feel like the image is getting bigger, is it an illusion?
So let's move this picture to the drawable-mdpi folder and try again and run the program again, as shown in the following:
This is certainly not an illusion, this is really too obvious, the picture has been enlarged!
So why is a picture that's going to be automatically magnified? And the magnification ratio is a bit too much. In fact, these scaling operations made by Android have strict rules and algorithms. There may be a lot of friends who have been doing Android for many years without noticing these scaling rules, because these details are too small, so in this tip we'll taken care the details.
First explain why a piece is magnified, and when we use the resource ID to refer to a picture, Android uses some rules to help us match the most appropriate image. What is the most suitable picture? For example, my mobile phone screen density is xxhdpi, then the drawable-xxhdpi folder picture is the most suitable picture. Therefore, when I refer to android_logo this picture, if the drawable-xxhdpi folder has this image will be used preferentially, in this case, the picture will not be scaled. However, if the drawable-xxhdpi folder does not have this picture, the system will automatically go to other folders to find this picture, priority will go to the higher density folder to find this image, our current scene is the drawable-xxxhdpi folder, And then found here there is no android_logo this picture, next will try to find a higher density of the folder, found no higher density, this time will go to drawable-nodpi folder to find this picture, found that there is no, then will go to lower density folder under the search, DRAWABLE-LDPI, drawable-mdpi, drawable-xhdpi-drawable-hdpi, respectively.
The overall matching rule is this, so for example now finally found under the drawable-mdpi folder Android_logo this picture, but the system will think you this picture is specifically designed for low-density equipment, If the image is used directly on the current high-density device, it is possible that the pixel is too low, so the system automatically helps us to do such a zoom operation.
In the same way, if the system is located under the Drawable-xxxhdpi folder to find this picture, it will think that this picture is designed for higher density devices, if the direct use of this image on the current device can be high-pixel situation, It will automatically help us to do a smaller operation. So, we can try to move the Android_logo map to the drawable-xxxhdpi folder below to get the result:
Can see, now the width and height of the picture is not mobile phone screen One-fourth, indicating that the picture is indeed reduced.
In addition, just in the introduction of the rules mentioned a drawable-nodpi folder, this folder is a density-independent folder, placed here in the picture system will not automatically scale it, the original picture is how big will actually show how big. But pay attention to the order of loading, drawable-nodpi folder is not found in the match density folder and higher density folder can not find the picture, so the picture placed in the drawable-nodpi folder is usually not recommended to be placed in other folders.
The reason why the picture is enlarged now that we have made it clear, then there is another problem, that is, how to determine the magnification multiplier? Unfortunately, I did not find the relevant documentation, but I summed up a rule, here to share with you.
Or look at just the DPI range-density table:
DPI Range |
density |
0DPI ~ 120dpi |
ldpi |
120DPI ~ 160dpi |
mdpi |
160DPI ~ 240dpi |
hdpi |
240DPI ~ 320dpi |
xhdpi |
320DPI ~ 480dpi |
xxhdpi |
480DPI ~ 640dpi |
xxxhdpi |
As you can see, the DPI range for each density has a maximum value, and the ratio between this maximum is the scale at which the image is automatically amplified by the system.
Accreditations, let's take a look at the example and modify the code in the layout file as follows:
<linearlayoutxmlns:android="Http://schemas.android.com/apk/res/android" Android:layout_width="Match_parent"android:layout_height="Match_parent" > <ImageViewandroid:id= "@+id/image"android:layout_width=" Wrap_content "android:layout_height=" Wrap_content "android:src=" @ Drawable/android_logo " /> <buttonandroid:layout_width="Wrap_content"android:layout_height= "Wrap_content" Android:text="Get picture width High"android:onclick="ButtonClick" /> </linearlayout>
As you can see, we have added a button and registered a click event for the button. Then handle this click event in mainactivity:
Public class mainactivity extends appcompatactivity {ImageView ImageView;@Override protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Setcontentview (R.layout.activity_main); ImageView = (ImageView) Findviewbyid (r.id.image); } Public void ButtonClick(View view) {Toast.maketext ( This,"Picture width:"+ Imageview.getwidth (), Toast.length_short). Show (); Toast.maketext ( This,"Picture height:"+ Imageview.getheight (), Toast.length_short). Show (); }}
Here you get the width and height of the picture in the Click event and use the toast hint. The code modifies so much that it can then move the picture to the drawable-mdpi folder.
Let's start with the analysis, the highest DPI value for mdpi density is 160, and the maximum DPI value for xxhdpi density is 480, so it's a 3 times-fold relationship, so we can guess, Images placed under the drawable-mdpi folder will be magnified 3 times times on xxhdpi density devices. corresponding to Android_logo, the original pixel is 270*480, which should be 810*1440 pixels after zooming in 3 times times. Run the program below with the effect as shown:
Validation passed. Let's try again and move the picture to the drawable-xxxhdpi directory. The maximum DPI value for the xxxhdpi density is 0.75 times times 640,480, so we can guess that the images placed in the drawable-xxxdpi folder will be reduced to 0.75 times times the size of the xxhdpi density device. 270*480 0.75 times times should be 202.5*360, because the pixel does not support the decimal point, then the rounding should be 203*360 pixels. Rerun the program as shown in the effect:
Verify the pass again. If you're interested, you can use a few other DPI drawable folders to try it out, which should all be appropriate for this set of scaling rules. So we can figure out why the image is scaled, and the specific zoom factor is clear, drawable related details you have explored very small.
But this is not the end of this article, I am going to talk about the scenarios we will encounter in actual development. According to the development recommendations of Android, we should try to prepare the image resources for each density of equipment to prepare a set, so that the compatibility of the program can achieve the best. But the reality is, the company's UI usually just give a set of picture resources, want them to each density of equipment to design a set of picture resources, and still according to our above-mentioned scaling rules to design, a little thought too happy. Yes, this is the real situation, so in this case, we should put the only one of the image resources in which density folder?
This can be analyzed, according to what we have just learned, if a picture is placed in a low-density folder, then the image on the high-density device will be automatically magnified, and if a picture is placed in a high-density folder, then the low-density device display pictures will be automatically reduced. Then we can estimate by the cost of the way, a picture has been reduced after the show actually does not have any side effects, but a picture of the original is magnified after the display means to occupy more memory. Because the image is magnified, the pixel becomes more, and each pixel is occupied with memory.
We can still use the example to intuitively understand, first move the android_logo.png picture to the drawable-xxhdpi directory, after running the program we see the program memory usage through Android Monitor:
As you can see, the memory used by the program is approximately 19.45M stable. Then move the android_logo.png picture to the drawable-mdpi directory and rerun the program, as shown in the following:
Now it's up to 23.40M, and the memory footprint has increased significantly. If you move the picture to the DRAWABLE-LDPI directory, you will find that it takes up more memory.
This example also verifies a problem, I believe that a lot of more experienced Android programmers may have encountered this situation, that is, when your project is getting bigger and larger, sometimes loading a picture under the DRAWABLE-HDPI, the program is directly oom collapsed, But if you put this picture in the drawable-xhdpi or drawable-xxhdpi, it will not collapse, in fact, this is the truth.
So after a series of analysis, the answer naturally comes out, the picture resources should be placed in high-density folder, so that the memory of the image can be saved, and the UI in the design of the picture should be as far as possible for high-density screen equipment to design. For now, the best place to put a picture resource is drawable-xxhdpi. Then some friends may ask, is there a higher density of drawable-xxxhdpi? Why don't you put it here? This is because the market 480dpi to 640dpi equipment is too little, if the image for this level of screen density to design pictures, the picture in the case of non-scaling itself is already very large, basic also can not afford to save the role of memory expenditure.
OK, the exploration of drawable micro-technique we are talking about here, this article is also set up a lot of my usual work experience summary, as well as through the experiment to draw some conclusions, I believe that can bring a lot of help to everyone. I will take the time to continue to prepare the new series of content, please look forward to.
Follow my public number, the first time to get a blog update reminders, there are many other technical information to share to everyone
Sweep the QR code below or search number Guolin_blog to follow:
Android drawable Micro tricks that you don't know about the drawable of those details