Android Resource picture reading mechanism

Source: Internet
Author: User

When you create a new Android project. In the Res directory will be the initiative to generate several drawable directory, drawable-ldpi,drawable-mdpi,drawable-hdpi, has been not very clear. The directory below which the picture should be placed. What are the different effects? have been all the time to create a new drawable directory without suffixes, pictures are thrown in, and now decided to thoroughly understand this matter.

1. Basic Knowledge

Density (density): Simply a scale factor used to convert the dip (device independent pixels) to the actual pixel px. The detailed formula is:

px = dip*density+0.5f;

Densitydpi:the screen density expressed asdots-per-inch. Simply say densitydpi = density*160

Drawable Directory In addition to these density class suffix, as well as-en for example, the English environment,-port for vertical screen, etc., here is not discussed. Be able to participate in http://developer.android.com/guide/topics/resources/providing-resources.html

Attach a table with the official screen size and density:



2. Why to Scale

To adapt to so many messy devices, Android officials recommend that you create different images for different density devices:

36x36 (0.75x) for low-density

48x48 (1.0xbaseline) for medium-density

72x72 (1.5x) for high-density

96x96 (2.0x) for extra-high-density

180x180 (3.0x) for extra-extra-high-density

192x192 (4.0x) for Extra-extra-extra-high-density (launcher icon only; see note above)

Here's the question, assuming you don't listen to the advice. Just a picture of a density? So when you encounter a different density of mobile phones, the system will be Good (no) heart (sentiment) of your map to zoom, according to the document, this is for your application more beautiful.

Scale formula: Scaled size = picture actual size x (phone density/image density)

The image density is determined by the suffix of the drawable directory where the picture resides.

For example, a 100x100 picture is placed in the MDPI directory. On HDPI's phone, scaled size = 100 * (1.5/1) = 150

It became a picture of 150*150.


3, Android:anydensity

(Some blogs on the internet are wrong to explain this attribute, so here's a special mention)

You can set such a property in the Androidmanifest.xml file: <supports-screens android:anydensity= "true"/>

Do not set the words of the default feel true.

As the document says (http://developer.android.com/guide/practices/screens_support.html), this value is assumed to be true and the scaling mechanism is pre-scaled (pre-scaling), Assuming false, the scaling mechanism is self-scaling (auto-scaling), and the difference is that pre-scaling is scaled at read time, scaling when drawing when self-scaling, and pre-scaling faster from the speed. Another very important difference. is to assume <supports-screensandroid:anydensity= "false"/>, which is applied when requesting screen parameters. The system will trick the app and tell it that you're running on a density 1 phone, no matter what the actual density is, for example, the actual phone is hdpi. Size 480*800, the system tells the app that the screen size is 320 (400/1.5) *533 (800/1.5), and then when the app draws the picture to (10,10) to (100,100) the area. The system converts it to (15,15) to (150,150), assuming you are directly manipulating these scaled graphs. There will be some unexpected problems. In short, it is recommended not to set this property to False.

According to my personal understanding, this false is to tell the system that the application does not support multi-resolution, so the system will feel that you only support the default resolution (MDPI), the system will give you a virtual MDPI device, let you show on the above, the system from the top of stretching or shrinking to the actual device. This is both slow and ineffective. So it's not recommended.


4, each folder read priority

If the project has an example of the following drawable folder:

Drawable

drawable-nodpi

drawable-ldpi

drawable-mdpi

drawable-hdpi

drawable-xhdpi.

(Assuming that you don't want the system to scale the picture, you can put the picture in the Drawable-nodpi folder, and the picture system that you read from that folder doesn't scale anyway.) )

(The following is known.) Images under the Drawable folder without suffixes are processed according to DRAWABLE-MDPI.)

Suppose there is a picture of the same name under these folders, which one should be read by the system?

Needless to say, if the cell phone density is the same as the corresponding density folder under the picture, that is it, suppose not?

Follow the source code to see how the system chooses the image (based on android4.4.2):

Imageview.java:

Setimageresource ()

ResolveUri ()

Resources.java:

Getdrawable ()

GetValue ()

Assetmanager.java:

Getresourcevalue ()

Native Loadresourcevalue ()

Frameworks/base/core/jni/android_util_assetmanager.cpp:

Android_content_assetmanager_loadresourcevalue ()

Frameworks/base/libs/androidfw/assetmanager.cpp:

Assetmanager::getresources ()

Assetmanager::getrestable ()

Frameworks/base/libs/androidfw/resourcetypes.cpp:

Restable::getresource ()

Restable::getentry ()

ssize_t restable::getentry (const package* Package, int typeindex, int entryindex, const restable_config* Config, CO      NST restable_type** outtype, const restable_entry** outentry, const type** outtypeclass) const{******** omitted *******   Const size_t NT = Alltypes->configs.size ();       for (size_t i=0; i<nt; i++) {Const restable_type* const THISTYPE = alltypes->configs[i];              if (Thistype = = NULL) continue;       Restable_config Thisconfig;           Thisconfig.copyfromdtoh (Thistype->config);  Omit ******* if (type! = NULL) {//Check if this one is less specific than the last found.  If So,//We'll skip it.           We checkstarting with things we are most care//about to those we least care about. if (!thisconfig.isbetterthan (bestconfig, config)) {//Is here Table_getentry (Alogi ("Thisconfig is worse than L                Ast!\n "));           Continue }} type = thisType;       offset = Thisoffset;       Bestconfig = Thisconfig;       Table_getentry (Alogi ("Best entry so far-using it!\n"));    if (!config) break; } ******** omit ******* return offset + dtohs (entry->size);}

Restable_config::isbetterthan ()

BOOL Restable_config::isbetterthan (const restable_config& O, const restable_config* requested) const {if (R                equested) {************** if (Screentype | | o.screentype) {if (density! = o.density) {  Density is tough.  Any density is potentially useful//because the system would scale it.                Scaling down//are generally better than scaling up. Default density counts as 160DPI (the system default)//Todo-remove Constants int                h = (density?density:160);                int L = (o.density?o.density:160);                bool Bimbigger = true;                    if (L > h) {int t = h;                    h = l;                     L = t;                Bimbigger = false;                } int reqvalue = (requested->density?requested->density:160); if (reqvalue >= h) {//RequestEd value higher than both L and H, give H return bimbigger;                    } if (l >= reqvalue) {//requested value lower than both L and H, give L                return!bimbigger; }//Saying that scaling down are 2x better than up if (((2 * l)-reqvalue) * H > Reqvalu                E * reqvalue) {return!bimbigger;                } else {return bimbigger; }} ***********}} return Ismorespecificthan (O);}


The key part has been marked with red characters, when there are pictures with the same name under multiple drawable. A resource ID corresponding to more than one picture, in the getentry there is a loop, with the Isbetterthan () function in the loop to select the most appropriate picture.

Can see, assuming that the picture does not indicate density. Density on the 160. This is also the drawable directory of the picture is mdpi feel the reason.

In the Isbetterthan function, the density is the density of the current resource, o.density is the density of the most suitable resource in the previous cycle, and Reqvalue is the request density.

Three If,

The first if: assuming that both density and o.density are smaller than reqvalue, the larger one is appropriate

The second if: assuming that both density and o.density are greater than reqvalue, then the smaller one is more appropriate

Third if: Assuming that the reqvalue size is between density and o.density, first infer

if ((((2 * l)-reqvalue) * h > Reqvalue * reqvalue)

This inference is that the request density and the smaller density difference is very small, and the larger one density difference is very large. Then it feels that the smaller density is more appropriate.

Test environment: Simulator +android4.4.2, in which XH and xxh are +android4.4.2 measured with a real machine. Among them ldpi besides Android4.4.2 also uses android2.3.1,hdpi except Android4.4.2 also uses Android2.1, the result is not different.

Test folder: drawable-ldpi,drawable-mdpi,drawable-hdpi,drawable-xhdpi,drawable-nodpi,drawable

Test results ():

How drawable-nodpi sometimes in front of the back? With two source codes, you're clear.

Frameworks/base/include/androidfw/resourcetypes.h:

    enum {        Density_default = aconfiguration_density_default,        density_low =aconfiguration_density_low,        Density_medium =aconfiguration_density_medium,        density_tv = Aconfiguration_density_tv,        DENSITY_HIGH = Aconfiguration_density_high,        Density_xhigh = Aconfiguration_density_xhigh,        density_xxhigh =ACONFIGURATION _density_xxhigh,        density_xxxhigh =aconfiguration_density_xxxhigh,        density_none =aconfiguration_density _none    };

Frameworks/native/include/android/configuration.h:

    Aconfiguration_density_default = 0,    Aconfiguration_density_low = +,    aconfiguration_density_medium = 160,    Aconfiguration_density_tv = 213,    Aconfiguration_density_high =    Aconfiguration_density_xhigh = +,    Aconfiguration_density_xxhigh = 480,    Aconfiguration_density_xxxhigh = 640,    Aconfiguration_density_none = 0xFFFF,

The image density value under the visible drawable-nodpi folder is 0xFFFF. That is, 65535. Bring in the deduction, as the result of a test.

No picture no truth, so put a hdpi environment of the test to try:

If you want to know which graph to read, you can:

Typedvalue typedvalue = new Typedvalue (); Getresources (). GetValue (r.drawable.test,typedvalue,true);// Then the typedvalue.string value is the picture path actually read

Android resource picture reading mechanism

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.