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
Related
I have a app which uses co-ordinates on the image to pin a marker.
final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (imageView.isReady()) {
sCoord = imageView.viewToSourceCoord(e.getX(), e.getY());
imageView.setPin(new PointF(sCoord.x,sCoord.y));
Toast.makeText(getApplicationContext(), "Single tap: " + ((int) convertPixelsToDp(sCoord.x)) + ", " + ((int) convertPixelsToDp(sCoord.y)), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Something is not right!", Toast.LENGTH_SHORT).show();
}
return true;
}
});
Now am doing some calculations on the point and points and changing the position of the marker. It's working fine on the device which am using but when I use another device, it's shows random location(which is obvious).
I tried this to change the co-ordinates(pixels) to dp unit and then pinning the image to that position, still it doesn't work.
/**
* 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 * (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 / (metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
return dp;
}
Let's say I have an floorplan of a store, I want a pin a marker near the door. So I take the co-ordinate and convert it to dp using above mentioned function,then I pass that dp location to another device and there am converting that dp to pixels and using that location to pin the marker, but it's not working. Showing random locations.
//trying
float x=convertDpToPixel(sCoord.x);
float y=convertDpToPixel(sCoord.y);
imageView.setPin(new PointF(x,y));
Any suggestion is welcomed. Thanks.
The approach to solve this problem is just to use a Percentage approach, to elaborate the given answer I am going to show some simple Math.
The process of this computation requires the following Values:
imageWidth = the width of the image from the left to right.
imageHeight = the height if the image from top to bottom.
xOccupation = the occupied with of the x-coordinate from left to right.
yOccupation = the occupied height of the y-coordinate from top to bottom.
To compute the xPercentage and yPercentage we are going to use this formula:
xPercentage = xOccupation/imageWidth
yPercentage = yOccupation/imageHeight
After getting those 2 values, you are now ready to send it to your server and access the same value in all kinds of device regardless of the size density.
The client device requires to recompute the x and y coordinates by doing the reverse formula.
new-x-coordinate = newImageWidth*xPercentage.
new-y-coordinate = newImageHeight*yPercentage.
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
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;
I want to place a button on image view at specific position.i.e at fixed x,y position. Is it possible to do that since android have different screen size for every device.
I have tried doing that using layout params but its not working properly.
POI3 = new Button(this);
POI3.setId(3);
POI3.setBackgroundColor(Color.TRANSPARENT);
POI3.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onButtonClick("3");
}
});
params = new RelativeLayout.LayoutParams(75, 75);
params.leftMargin = 466;
params.topMargin = 255;
// This line defines how params.leftMargin and params.topMargin are interpreted.
// In this case, "<80,90>" means <80,90> to the right of the yellow ImageView.
params.addRule(RelativeLayout.RIGHT_OF, yellow_iv_id);
rl.addView(POI3, params);
for set your button in fix position you must use dp instead of xp,use following code to convert that:
/**
* 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 * (metrics.densityDpi / 160f);
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 / (metrics.densityDpi / 160f);
return dp;
}
I'm adding a widget to a layout dynamically.
I need to set the widget width as 100 through code like the below :
Width = 100;
How can I convert the above given value to dps in android
/**
* 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 / (metrics.densityDpi / 160f);
return dp;
}
Credit: Converting pixels to dp