Passing from one unit to another in android? - android

Well, i been trying to figure out, is there a simple way to pass from dp or milimetres or even inches to px. (like: 6dp would be 20px)
It seems everything is usually done in px but i want to use these in orther to keep the proportions in different screens and have a rough sense of how big is going to be (guessing with pixels feels really...bothering)
Thanks in advance and sorry if the question is too vague.

There is no way to convert milimetres or even inches to px programmatically. If you want to support different screens, you can follow the document here.
To convert dp to px, you can also use the following method:
/**
* Convert dp to px.
* #param context
* #param dp the input dp.
* #return the output px.
*/
public static int dpToPx(Context context, int dp) {
float density = context.getResources().getDisplayMetrics().density;
return (int) (dp * density + 0.5);
}
Update:
Here is how to get a device's width and height pixels:
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;

Related

Android: How to account for pixel density

I am really struggling with trying to handle the pixel density of screens. How do I make my application look the same on all devices? I thought the answer might be changing the units from dp to px:
public static int dpToPx(int dp) {
return (int)(dp / Resources.getSystem().getDisplayMetrics().density);
}
But this didn't seem to work either and I can't seem to find an answer on how to handle this.
If you are in an activity or fragment then, you can call the getResources() method. Then you can convert the dp to px by the below method:
Formula: px = dp * density
public static int dpToPx(int dp) {
return (int)(dp * getResources().getDisplayMetrics().density);
}

pixels to dp convertor based on ppi

I am converting px to dp for given graphics. Going through docs I noticed that 1dp = 3px for 480ppi screen(xxhdpi).
I am testing it on Redmi Note3 which has approx 403 ppi.
I have been provided margins in pixels by my designer. Should I convert those into pixels to by using 1:3 ratio or it should be different
/**
* This method converts dp unit to equivalent pixels, depending on device density.
*
* #param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
* #param context Context to get resources and device specific display metrics
* #return A float value to represent px equivalent to dp depending on device density
*/
public static float convertDpToPixel(float dp, Context context){
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float px = dp * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
return px;
}
/**
* This method converts device specific pixels to density independent pixels.
*
* #param px A value in px (pixels) unit. Which we need to convert into db
* #param context Context to get resources and device specific display metrics
* #return A float value to represent dp equivalent to px value
*/
public static float convertPixelsToDp(float px, Context context){
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
return dp;
}
for more information look into this SOF post Converting pixels to dp

Converting dp into pixels for multiple screen support

I am having a hard time to make this right.
Basically I am creating an ImageView and applying a LayoutParameter to it.
LayoutParams lp = new LayoutParams(width, height);
lp.gravity = Gravity.CENTER;
I know that width and height parameters receive pixel numbers, so I am passing them in DP and converting it to absolute pixels using:
public int convertToPixels(float dpSize){
final float density = getResources().getDisplayMetrics().density;
return ((int) (dpSize * density + 0.5f));
}
As far I know, this should make a drawable fill exactly the same area in different screens, right? Unfortunately, that is not happening at all.
Is there something wrong with these methods I am using?
These two emulators below have the same image and the same amount of DP.
Left emulator is 1.0 density and right one is 2.0. Why still does it look
so different ? Don't undertand..
Use :
public class Convert{
public static float convertDpToPixel(float dp){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return Math.round(px);
}
}
Just use it in a static way:
float requiredPixel = Convert.convertDpToPixel(16.0);
For more info: https://developer.android.com/guide/practices/screens_support.html

How to convert DP, PX, SP among each other, especially DP and SP?

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

View.setPadding accepts only in px, is there anyway to setPadding in dp?

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

Categories

Resources