Load dimension value from res/values/dimension.xml from source code

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"...

Upvotes: 432

Views: 264817

Answers (11)

Lance Samaria
Lance Samaria

Reputation: 19632

Kotlin:

// Activity
val pixels: Float = resources.getDimension(R.dimen.your_dimen_id)

// Fragment
val pixels: Float = (activity as? MainActivity)?.resources?.getDimension(R.dimen.your_dimen_id) ?: return

Afterwards, if you need to convert Pixels to DP:

fun convertPixelsToDp(px: Float, context: Context): Float {
    return px / (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}

Upvotes: 2

Dživo Jelić
Dživo Jelić

Reputation: 2151

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()
}

Upvotes: 3

Nico
Nico

Reputation: 2882

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);

Upvotes: 13

NeuraCache
NeuraCache

Reputation: 14174

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

Upvotes: 973

Seven
Seven

Reputation: 197

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

Upvotes: 2

Gibolt
Gibolt

Reputation: 47297

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

Upvotes: 14

Jonny Right
Jonny Right

Reputation: 566

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

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

Upvotes: 16

Suragch
Suragch

Reputation: 512824

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);

Upvotes: 22

AndroidLad
AndroidLad

Reputation: 697

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);

Upvotes: 5

Ovidiu Latcu
Ovidiu Latcu

Reputation: 72341

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

Upvotes: 19

Jug6ernaut
Jug6ernaut

Reputation: 8325

Context.getResources().getDimension(int id);

Upvotes: 24

Related Questions