402

I'd like to load the value as it is. I have two dimension.xml files, one in /res/values/dimension.xml and the other one in /res/values-sw360dp/dimension.xml.

From source code I'd like to do something like

getResources().getDimension(R.dimen.tutorial_cross_marginTop);

This works but the value I get is multiplied times the screen density factor (1.5 for hdpi, 2.0 for xhdpi, etc).

I also tried to do

getResources().getString(R.dimen.tutorial_cross_marginTop);

This would work in principle but I get a string that ends in "dip"...

Vadim Kotov
  • 7,766
  • 8
  • 46
  • 61
Héctor Júdez Sapena
  • 5,129
  • 3
  • 22
  • 30
  • 1
    I wonder if it is bug in Android as Resources has method `getDimensionPixelSize(int id)` that exactly states that it returns in Pixel, so `getDimension(int id)` should return in dp (dependency independent units), that would be ready for use, e.g. with View `setPadding` – Paul Verest Sep 12 '14 at 09:24

11 Answers11

930

In my dimens.xml I have

<dimen name="test">48dp</dimen>

In code If I do

int valueInPixels = (int) getResources().getDimension(R.dimen.test)

this will return 72 which as docs state is multiplied by density of current phone (48dp x 1.5 in my case)

exactly as docs state :

Retrieve a dimensional for a particular resource ID. Unit conversions are based on the current DisplayMetrics associated with the resources.

so if you want exact dp value just as in xml just divide it with DisplayMetrics density

int dp = (int) (getResources().getDimension(R.dimen.test) / getResources().getDisplayMetrics().density);

dp will be 48 now

Alireza Noorali
  • 3,777
  • 2
  • 26
  • 71
AndroidGecko
  • 13,876
  • 3
  • 32
  • 49
  • 4
    I think the documentation is particularly unclear here. "Unit conversions are based on the current DisplayMetrics associated with the resources." when all they want to say is that they convert to pixels. – Trilarion Dec 12 '15 at 22:31
  • If you are essentially going to be discarding the display metrics multiplier, you may as well just define your dimension in px. 48px. getDimension(R.dimen.test) will return 48. – Michael Peterson Nov 06 '17 at 14:58
  • Not work for me: https://stackoverflow.com/questions/55972518/not-correct-return-text-size-in-sp – Alex May 04 '19 at 11:28
  • @Trilarion They do not simply convert to pixels, though. They are saying that `dp` will give the scaled pixel value relative to the scale of the resource object used to retrieve it. Once you get into various ways to obtain resources, this will be more relevant. For simplicity, you can think of it as being relative to screen scale. There is also `sp`, or pixels relative to the system text size, and `px`, or pixels directly. Each is different and has a different purpose. – Abandoned Cart Jun 01 '19 at 22:59
  • If you want sp value from dimens.xml, then you'll need int sp = (int) (getResources().getDimension(R.dimen.test) / getResources().getDisplayMetrics().scaledDensity) – Seven Nov 10 '20 at 06:51
23
Context.getResources().getDimension(int id);
Jug6ernaut
  • 8,073
  • 2
  • 25
  • 26
19

The Resource class also has a method getDimensionPixelSize() which I think will fit your needs.

Ovidiu Latcu
  • 70,421
  • 14
  • 74
  • 84
  • 25
    This is wrong! the metrics conversion also does occurs in `getDimensionPixelSize()` if you can refer the docs it clearly states **Returns** `Resource dimension value multiplied by the appropriate metric and truncated to integer pixels.` – Muhammad Babar Dec 10 '13 at 07:28
  • This is wrong. The metrics conversion occurs using this method as well. – Michael Peterson Nov 06 '17 at 14:45
19

For those who just need to save some int value in the resources, you can do the following.

integers.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="default_value">100</integer>
</resources> 

Code

int defaultValue = getResources().getInteger(R.integer.default_value);
Suragch
  • 428,106
  • 278
  • 1,284
  • 1,317
  • 2
    Thank you for this, was more of what I was looking for even though maybe not for others, but this solution provided actually provided me with some insight into other areas of my code – JamisonMan111 Nov 19 '17 at 01:42
15

You can use getDimensionPixelOffset() instead of getDimension, so you didn't have to cast to int.

int valueInPixels = getResources().getDimensionPixelOffset(R.dimen.test)
Eric Aya
  • 69,000
  • 34
  • 174
  • 243
Jonny Right
  • 488
  • 3
  • 10
12

Use a Kotlin Extension

You can add an extension to simplify this process. It enables you to just call context.dp(R.dimen. tutorial_cross_marginTop) to get the Float value

fun Context.px(@DimenRes dimen: Int): Int = resources.getDimension(dimen).toInt()

fun Context.dp(@DimenRes dimen: Int): Float = px(dimen) / resources.displayMetrics.density

If you want to handle it without context, you can use Resources.getSystem():

val Int.dp get() = this / Resources.getSystem().displayMetrics.density // Float

val Int.px get() = (this * Resources.getSystem().displayMetrics.density).toInt()

For example, on an xhdpi device, use 24.dp to get 12.0 or 12.px to get 24

Gibolt
  • 33,561
  • 12
  • 157
  • 107
5

You can write integer in xml file also..
have you seen [this] http://developer.android.com/guide/topics/resources/more-resources.html#Integer ? use as .

 context.getResources().getInteger(R.integer.height_pop);
AndroidLad
  • 686
  • 7
  • 14
3

Here is a better solution, not involving double conversion from dp to px then px to dp:

In Kotlin

fun Resources.getRawDimensionInDp(@DimenRes dimenResId: Int): Float {
    val value = TypedValue()
    getValue(dimenResId, value, true)
    return TypedValue.complexToFloat(value.data)
}
// Usage: 
resources.getRawDimensionInDp(R.dimen.my_dimen_id)

In Java

public class ResourcesUtil {
    static Float getRawDimensionInDp(Resources resources, @DimenRes int dimenResId) {
        TypedValue value = new TypedValue();
        resources.getValue(dimenResId, value, true);
        return TypedValue.complexToFloat(value.data);
    }
}

// Usage: 
ResourcesUtil.getRawDimensionInDp(resources, R.dimen.my_dimen_id);
Nico
  • 2,189
  • 1
  • 6
  • 11
2
    This works but the value I get is multiplied times the screen density factor
  (1.5 for hdpi, 2.0 for xhdpi, etc).

I think it is good to get the value as per resolution but if you not want to do this give this in px.......

Density-independent pixel (dp)

A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way. The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.

I think it is good to change the value as per resolution but if you not want to do this give this in px.......

refer this link

as per this

dp

Density-independent Pixels - An abstract unit that is based on the physical density of the screen. These units are relative to a 160 dpi (dots per inch) screen, on which 1dp is roughly equal to 1px. When running on a higher density screen, the number of pixels used to draw 1dp is scaled up by a factor appropriate for the screen's dpi. Likewise, when on a lower density screen, the number of pixels used for 1dp is scaled down. The ratio of dp-to-pixel will change with the screen density, but not necessarily in direct proportion. Using dp units (instead of px units) is a simple solution to making the view dimensions in your layout resize properly for different screen densities. In other words, it provides consistency for the real-world sizes of your UI elements across different devices.

px

Pixels - Corresponds to actual pixels on the screen. This unit of measure is not recommended because the actual representation can vary across devices; each devices may have a different number of pixels per inch and may have more or fewer total pixels available on the screen.

Dheeresh Singh
  • 15,570
  • 3
  • 36
  • 36
2

If you just want to change the size font dynamically then you can:

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.tutorial_cross_marginTop))

As @achie's answer, you can get the dp from dimens.xml like this:

val dpValue = (resources.getDimension(R.dimen.tutorial_cross_marginTop)/ resources.displayMetrics.density).toInt()

or get sp like this

val spValue = (resources.getDimension(R.dimen.font_size)/ resources.displayMetrics.scaledDensity).toInt()

About Resources.java #{getDimension}

    /**
     * Retrieve a dimensional for a particular resource ID.  Unit 
     * conversions are based on the current {@link DisplayMetrics} associated
     * with the resources.
     * 
     * @param id The desired resource identifier, as generated by the aapt
     *           tool. This integer encodes the package, type, and resource
     *           entry. The value 0 is an invalid identifier.
     * 
     * @return Resource dimension value multiplied by the appropriate 
     * metric.
     * 
     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
     *
     * @see #getDimensionPixelOffset
     * @see #getDimensionPixelSize
     */

Resource dimension value multiplied by the appropriate

Seven
  • 147
  • 1
  • 5
0

Two helper functions I wrote in kotlin for this

/**
 * Gets the float value defined in dimens
 * Define float value as following
 * Example:
 * <item name="example" format="float" type="dimen">1.0</item>
 */
fun Resources.getFloatDimension(dimensResourceId: Int): Float {
    val outValue = TypedValue()
    this.getValue(dimensResourceId, outValue, true)
    return outValue.float
}

/**
 * Gets the dp value defined in dimens
 * Example:
 * <dimen name="example">12dp</dimen>
 *
 * Will return 12
 */
fun Resources.getDimensionInDp(dimensResourceId: Int): Int {
    return (getDimension(dimensResourceId) / displayMetrics.density).toInt()
}
Dživo Jelić
  • 1,604
  • 2
  • 22
  • 47