Does setWidth(int pixels) use device independent pixel or physical pixel as unit?
For example, does setWidth(100) set the a view's width to 100 dips or 100 pxs?
Thanks.
It uses pixels, but I'm sure you're wondering how to use dips instead. The answer is in TypedValue.applyDimension(). Here's an example of how to convert dips to px in code:
// Converts 14 dip into its equivalent px
Resources r = getResources();
int px = Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 14,r.getDisplayMetrics()));
The correct way to obtain a constant number of DIPs in code is to create a resources XML file containing dp values a bit like:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="image_width">100dp</dimen>
<dimen name="image_height">75dp</dimen>
</resources>
Then refer to the resource in your code like so:
float width = getResources().getDimension(R.dimen.image_width));
float height = getResources().getDimension(R.dimen.image_height));
The float you have returned will be scaled accordingly for the pixel density of the device and so you don't need to keep replicating a conversion method throughout your application.
Method setWidth(100), set 100 px as width(not in dp).So you may face width varying problems on different android phones.So use measurement in dp instead of pixels.Use the below code to get measurement in dp of sample width=300px and height=400px.
int width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 300, getResources().getDisplayMetrics());
int Height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 400, getResources().getDisplayMetrics());
float dps = 100;
float pxs = dps * getResources().getDisplayMetrics().density;
Source (#Romain Guy)
Based on above answers which works fine to me, i generate some helper methods, just add them in your utils to use them in whole project.
// value in DP
public static int getValueInDP(Context context, int value){
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, context.getResources().getDisplayMetrics());
}
public static float getValueInDP(Context context, float value){
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, context.getResources().getDisplayMetrics());
}
// value in PX
public static int getValueInPixel(Context context, int value){
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, value, context.getResources().getDisplayMetrics());
}
public static float getValueInPixel(Context context, float value){
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, value, context.getResources().getDisplayMetrics());
}
It uses pixels. here's a Kotlin extension function to convert pixels to dp
fun Context.pxToDp(value: Float):Int{
val r: Resources = resources
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, value, r.displayMetrics
).roundToInt()
}
Pixels of course, the method is asking for pixels as parameter.
Related
I have known the difference among DP, SP and PX. And after searching this topic, I found nothing satisfying me completely. Maybe this post is a duplicate, but I still want to know what is the formula of converting from DP to PX, and DP to SP, from SP to PX, from PX to SP, from SP to DP, from DP to SP? I have known some codes to do this, but they are imperfect.
DP to PX:
public static int dpToPx(float dp, Context context) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
}
SP to PX:
public static int spToPx(float sp, Context context) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
}
DP to SP:
public static int dpToSp(float dp, Context context) {
return (int) (dpToPx(dp, context) / context.getResources().getDisplayMetrics().scaledDensity);
}
The accepted answer is missing a few useful conversions.
SP to PX
float sp = 20;
float px = sp * getResources().getDisplayMetrics().scaledDensity;
or
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
PX to SP
float px = 70;
float sp = px / getResources().getDisplayMetrics().scaledDensity;
DP to PX
float dp = 20;
float px = dp * getResources().getDisplayMetrics().density;
or
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
PX to DP
float px = 70;
float dp = px / getResources().getDisplayMetrics().density;
Notes
The floats I chose above (20 and 70) were arbitrary values. You can plug in different numbers if you like.
px refers to pixels. The number of pixels that a device has per inch of screen space is called the density.
dp means density-independent pixels. That is, no matter what device is used, the actual size should be the same. For example, if I set a view to be 100 dp wide, it will have the same width on a new high density phone as it does on an old low density phone. (If I had set the width to 100 px, on the other hand, it would appear large on a low density phone and small on a high density phone.) Density is measured in dots per inch (DPI). The formula is px = dp * density. So you just multiply or divide by the density to convert between px and dp.
sp means scale-independant pixels. It is just used for fonts, not views. It is similar to dp except it also factors in the user preferences. This density with user preferences taken into account is known as scaled density. Setting a TextView font to a size of 30 sp, for example, will make the text generally appear to be the same physical size on all devices. However, your grandmother may have her preferred font size maxed all the way up in her phone settings, so 30 sp text will look bigger on her phone than it does on yours. The formula is px = sp * scaledDensity.
Meaning of DP and SP
DP to SP conversion is not generally useful
For converting Dimension to Integer or Pixel you need to use "getDimensionPixelSize(R.dimen.your_dp_value)" function, Like...
Make a value in dimens.xml
<dimen name="padding_10">10dp</dimen>
Now for That value in pixel or integer you can use as like below:
int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.padding_10);
For kotlin I created an extension function:
fun Number.spToPx(context: Context) = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, this.toFloat(), context.resources.displayMetrics).toInt()
You can use it like 16.spToPx(context) or 16.5.spToPx(context)
(I place such functions in a KotlinExtensions.kt file)
You can write a method, that doesn't need context or resources:
public static int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
public static int spToPx(int sp) {
return (int) (sp * Resources.getSystem().getDisplayMetrics().scaledDensity);
}
By analogy, other quantities can be converted.
According to TypedValue#applyDimension source code and take advantage of Kotlin extension:
val Float.toSp get() = this * Resources.getSystem().displayMetrics.scaledDensity
Other extensions from link
val Float.toPx get() = this * Resources.getSystem().displayMetrics.density
val Float.toDp get() = this / Resources.getSystem().displayMetrics.density
My font size is 12dp.
I'm setting the font using TextPaint, since I'm using a span. The problem is the parameter that TextPaint accepts is in float. I'm wondering how can I convert 12 dp to float?
From android.content.res.Resources.getDimension(int id):
float twelveDp = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 12,
mContext.getResources().getDisplayMetrics() );
Try this:
public static float dipToPixels(Context context, float dipValue){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics);
}
You can try following:
// Convert the sp to pixels
final float scale = getResources().getDisplayMetrics().scaledDensity;
int mTextSizeP = (int) getResources().getDimensionPixelSize(R.dimen.text_size) / scale );
I have already have text_size defined in res/values/dimens.xml :
<resources>
<dimen name="text_size">12sp</dimen>
</resources>
Is it possible to specify the pixel unit in code.
What I mean is, say I have a layout and I want the size to be 20dp, then is there any way to do so without writing in a layout xml
In a view:
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
float dp = 20f;
float fpixels = metrics.density * dp;
int pixels = (int) (fpixels + 0.5f);
In an Activity, of course, you leave off the getContext().
To convert from scaled pixels (sp) to pixels, just use metrics.scaledDensity instead of metrics.density.
EDIT: As #Santosh's answer points out, you can do the same thing using the utility class TypedValue:
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
float dp = 20f;
float fpixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics);
int pixels = Math.round(fpixels);
For sp, substitute TypedValue.COMPLEX_UNIT_SP for TypedValue.COMPLEX_UNIT_DIP.
Internally, applyDimension() does exactly the same calculation as my code above. Which version to use is a matter of your coding style.
You can use
float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());
now, the value of pixels is equivalent to 20dp
The TypedValue contains other similar methods that help in conversion
Android function View.setPadding(int left, int top, int right, int bottom) only accepts values in px but I want to set padding in dp. Is there any way around it?
Straight to code
int padding_in_dp = 6; // 6 dps
final float scale = getResources().getDisplayMetrics().density;
int padding_in_px = (int) (padding_in_dp * scale + 0.5f);
If you define the dimension (in dp or whatever) in an XML file (which is better anyway, at least in most cases), you can get the pixel value of it using this code:
context.getResources().getDimensionPixelSize(R.dimen.your_dimension_name)
There is a better way to convert value to dp programmatically:
int value = 200;
int dpValue = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
value,
context.getResources().getDisplayMetrics());
Then apply dpValue to your method, for example: setPadding(dpValue,dpValue,dpValue,dpValue);
Here's Kotlin version based on accepted answer:
fun dpToPx(dp: Int): Int {
val scale = resources.displayMetrics.density
return (dp * scale + 0.5f).toInt()
}
You can calculate the pixels for a specific DPI value: http://forum.xda-developers.com/showpost.php?p=6284958&postcount=31
I've the same problem. The only solution i've found (it will not really help you :) ) is to set it in the Xml file.
If you can get the density from the code, you can use the convertion: "The conversion of dip units to screen pixels is simple: pixels = dips * (density / 160)." (from http://developer.android.com/guide/practices/screens_support.html )
Edit: you can get the screen density: http://developer.android.com/reference/android/util/DisplayMetrics.html#densityDpi
I'm dynamically generating a grid of EditText views in code based on a specified number of rows and columns. I want each of the EditText views to be the same width (e.g., 100dp).
Although I can set the size of the views with either setWidth or by creating a LayoutParam object, I only seem able to specify the value in pixels. I instead want to use the DP (density independent) units, similar to what I've done using an XML layout.
How can this be done in code?
I have a method in a Utils class that does this conversion:
public static int dip(Context context, int pixels) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (pixels * scale + 0.5f);
}
float value = 12;
int unit = TypedValue.COMPLEX_UNIT_DIP;
DisplayMetrics metrics = getResources().getDisplayMetrics();
float dipPixel = TypedValue.applyDimension(unit, value, metrics);
Using the below code i was able to do it.
int width = (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (100)your Size
in int, getResources().getDisplayMetrics());