How does the system find the best-matching Resource? - android

I have a hdpi device.
DPI: hdpi, density: 1.5, densityDpi: 240, sw: 320
values and values-xxhdpi folders.
Why Android takes dimes from values-xxhdpi not from values?
I assumed it should take it from a smaller folder.
And default values is mdpi and also hdpi is closser to mdpi then to xxhdpi.
Could you please tell me where am I going wrong?

Densities are handled differently than other resource set constraints.
Android density resource set constraints are designed for use with drawable and mipmap. For those resources, Android can automatically convert the resource from one density to another, by upsampling or downsampling the image. This is not the case for other resource set constraints. For example, Android cannot automatically convert an English string resource to Chinese.
When it comes to finding a compatible resource, if you use densities as a constraint for the type (e.g., values), Android behaves as though it can convert the resource from one density to another... even for resource types where that is impossible. So, Android is choosing the closest density, using whatever algorithm it would use for choosing the image to convert, even though you are using the density qualifier on something other than images.
Using density as a qualifier for anything other than drawable or mipmap is a code smell. You are unlikely to get what you want.

Related

1080x1920 420dpi screen not accessing from sw420dp

I am creating different values folder for supporting different screen sizes.The following are the folders:
values-sw320dp-hdpi
values-sw320dp-xhdpi
values-sw320dp-xxhdpi
values-sw420dpi
values-sw560dpi
values-sw480dp-hdpi
values-sw480dp-xhdpi
values-sw480dp-xxhdpi
values-sw600dp
values-sw720dp
In the list of devices provided by Android Studio there is 1080x1920 420dpi.It should access dimens values from values-sw420dp.But instead it is accessing from sw320dp-xxhdpi.The layout in 1080x1920 420dpi **looks slightly different from **1080x1920 xxhdpi. Can anyone explain to me why it is not accessing from its own folder?Or could you explain to me the correct way to create a layout so that it support different screen sizes with different densities?I have referred different sites.They are confusing..Please help me!!
I am creating different values folder for supporting different screen sizes.
First, using density qualifiers (e.g., -xhdpi) on resource types other than drawable and mipmap is a serious code smell. Almost assuredly, you are not going to get the results that you expect.
Second, there is no -sw420dpi or -sw560dpi qualifier. You could have -sw420dp or -sw560dp, to say that you want to use these resources for those screen size thresholds. However, such directories would never be used, because of your density qualifiers on directories like values-sw320dp-hdpi.
In the list of devices provided by Android Studio there is 1080x1920 420dpi.It should access dimens values from values-sw420dp
No, it should not.
The smallest width of that screen is 1080px. 1080px, at 420dpi, is 411dp (1080 * 160 / 420). 411 < 420. Hence, anything that is -sw420dp will not qualify.
But instead it is accessing from sw320dp-xxhdpi.
Partially, that is because 411 is lower than 420.
Partially, that is because you are using density qualifiers here, which short-circuit a lot of the "normal" rules for resource selection.
The layout in 1080x1920 420dpi **looks slightly different from **1080x1920 xxhdpi.
Your question has no layouts, so nobody can comment on that.
Can anyone explain to me why it is not accessing from its own folder?
There is no "its own folder".
Or could you explain to me the correct way to create a layout so that it support different screen sizes with different densities?
Use layout resources based on screen size and (perhaps) orientation (e.g., res/layout-sw420dp/)
Use dimen resources measured in sp (for sizing text or things that are dominated by text) or dp (for everything else) in those layout resources (e.g., <dimen name="margin">16dp</dimen>)
Use density qualifiers, and maybe size qualifiers, for drawable and mipmap resources (e.g., res/drawable-hdpi/)
Frequently, that is sufficient.
I have referred different sites.They are confusing
Perhaps consider reading a book.

What order does Android read values folders?

In my Android project I have multiple values folders with extensions such as -hdpi, -xhdpi, and -sw720dp. In all of these folders I have dimens.xml and the same names for values in that xml file. If I have a device that has a width of 720 dp and is counted as an xhdpi device (as an example), then from what folder does Android read the values from? Also, in general, how does Android prioritize the different values folders?
Also, in general, how does Android prioritize the different values folders?
Generally speaking, Android takes the resources from the resource set that has the resource in question and has the most important distinct qualifier. Here, "most important" means "appears highest in Table 2 on this Web page", and "distinct" means "nobody else has that particular qualifier". Though things get a bit weird with screen sizes and densities.
I have multiple values folders with extensions such as -hdpi, -xhdpi, and -sw720dp. In all of these folders I have dimens.xml and the same names for values in that xml file.
IMHO that is a serious code smell. Use density-independent units of measure (e.g., dp), in which case you should not need different dimension resources based upon screen density. Having different ones based upon screen size is reasonable (e.g., bigger margins on tablets), though the mix then would be something like res/values/dimens.xml and res/values-sw720dp/values.xml.
If I have a device that has a width of 720 dp and is counted as an xhdpi device (as an example), then from what folder does Android read the values from?
-swNNNdp is higher in Table 2 than is -hdpi or -xhdpi, and so it should be considered first. Note that the size resource set qualifiers (e.g., -large, -swNNNdp) are for the specified size or larger. So, if your device has 720dp or more in the smallest width, your -sw720dp resource should be used.

Drawables not scaling for missing density buckets, if using drawable references

First, some background on what I'm doing. If you are familiar with references in general (simple concept), just skip to section 2, please.
1 The concept of density references
Usually, we use drawables in folders such as drawable-mdpi, drawable-hdpi and so on. Example:
/drawable-mdpi
./figure.png (24x24 pixels)
/drawable-hdpi
./figure.png (36x36 pixels)
[...]
However, another way to achieve (the same?) behavior is defining the same drawable, in different sizes, inside drawable-nodpi, and then referencing each size in values-mdpi, values-hdpi and so on through drawable references. Example:
/drawable-nodpi
./figure_24.png
./figure_36.png
/values-mdpi
./refs.xml
/values-hdpi
./refs.xml
Each refs.xml file should contain lines like this (example for /values-mdpi/refs.xml):
<item name="figure"
type="drawable">#drawable/figure_24</item>
That way, you can reference the same R.drawable.figure as you would without references. I've found this to be helpful when you need to address the same image in different sizes (e.g., using the same image in 24/36/48/72 and 48/72/96/144) without resizing, because you can reference the same image twice (e.g. again, the 48 and 72px images) without replicating images (thus avoiding bloating apk size).
2 Density references don't work if one is missing
As known, Android does not need all bucket densities to display a drawable properly [1]. For example, you may omit drawable-ldpi entirely and it will load and scale those in other drawable-* folders, presenting it for you in the appropriate size in the tested density. In fact, many apps (including from Google) already omit ldpi and nobody notices.
However, I noticed that, when using drawable references (see section 1, above), this behavior changes. If I omit the reference xml file in the density folder, and try to display that drawable in that density, Android will retrieve the highest density drawable variation, but will not resize it according to that density.
Let me give you an example to make it clearer: if, using referenced drawables, I omit values-ldpi/refs.xml, Android will retrieve the drawable from values-xxhdpi (the highest I provide for this arbitrary drawable) and show this in the size corresponding to xxhdpi, and not ldpi, as it should. Therefore, any layouts displayed in a ldpi device will have huge images. See images below:
A) Normal drawables work fine even if LDPI drawable is missing:
A) Referenced drawables don't work if one density reference is missing (I didn't provide an explicit variant in values-ldpi/refs.xml):
Nevermind, I tested in an ldpi emulator right now and it works. So it's one of those bugs that only affect the layout preview pane in the IDE.
Yes, I should have tested in an ldpi emulator before asking. :)

Galaxy S4 taking values from MDPI?

I want to use separate values for each density, so I created different values folders for each one,
values
values-ldpi
values-mdpi
values-hdpi
values-xhdpi
values-xxhdpi
in each of the strings.xml file I wrote the density (for values-xxhdpi i have a string with the text "xxhdpi"), but when I run this on GS4, I get the "mdpi" string,
I also did create separate layout folders, but always taking layout-mdpi density
any clue of what might be going on ?
It looks a bit funny to me to define layouts according to density and not size. Drawable and other similar resources depend on density, but layouts depend on size.
See here : http://developer.android.com/guide/practices/screens_support.html
For values, you could give it a try with values-normal, values-large, etc.
I write this although what you did is supposed to work according to this thread : https://stackoverflow.com/a/9639280/693752
Also, this resource is interesting to you :
http://developer.android.com/guide/topics/resources/providing-resources.html#BestMatch
---- UPDATE ----
Look at this answer from GodFather : https://stackoverflow.com/a/20521720/693752
(Note that density qualifiers are even fuzzier -- -mdpi will be used
for any device density, in the absence of a better match, as density
qualifiers are designed to be used only on drawable directories, where
Android can apply resampling algorithms. Using density qualifiers on
anything other than drawables and maybe dimension resources is a code
smell.)

How to determine which resource file is being used and why?

I'm testing one of my layouts using the different devices defined in the graphical layout editor in Eclipse. Due to some of the devices' varying resolutions I had to define different dimens.xml files to define specific font sizes so the design would look correct.
I have a dimens.xml file in each of the following resource folders:
values
values-sw1280dp
values-sw640dp
values-sw800dp
values-sw800dp-large
For whatever reason the device 7in WSVGA (Tablet) uses the dimens.xml in the values folder. But according to the device configuration the resolution for this device is 1024 x 600, so shouldn't it be using the dimens.xml defined in values-sw800dp-large?
Anyone have any idea?
It won't use values-sw800dp-large because that qualifier means that the smallest dimension must be at least 800dp. Also note that these are dp values, not pixels. So if the device is hdpi, 800dp is 1200 pixels.
If you're doing this in an emulator, there is a weird interaction with device display density and scaling of the emulator display. So, for instance, if your device is supposed to be hdpi, it may actually be treated as an mdpi display unless you specify a scaling.

Categories

Resources