I read here about converting dp units to pixel units. But I cant understand the 0.5f. Where does this number come from and what is the use of it?
// The gesture threshold expressed in dp
private static final float GESTURE_THRESHOLD_DP = 16.0f;
// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);
// Use mGestureThreshold as a distance in pixels...
Casting floating point numbers to integer will floor them.
That 0.5f is to round the number:
x = (int) 3.9
print x // 3
x = (int) 3.9 + 0.5f
print x // 4
Its to round things. Scale may be a decimal (like 1.5). This means the product may not be a whole number. Adding .5 then converting to int ensures that the number rounds up if the number is more than halfway between two integers, and down if its less than halfway.
Related
In Canvas, drawing an rectangle with RectF, need set top and left in dp or px?
Integer padding = 10;
Integer width = 100; // It is dp or px?
Integer height = 50;
RectF position = new RectF();
position.top = 0 + padding;
position.bottom = position.top + height;
position.left = 0 + padding;
position.right = position.left + width;
http://developer.android.com/intl/es/reference/android/graphics/RectF.html
It does not indicate if the values are represented in px or dp.
As has already been pointed out, Canvas and RectF use px and not dp.
As for the documentation, the documentation for Canvas
(http://developer.android.com/intl/es/reference/android/graphics/Canvas.html)
and RectF only mention pixels.
Since it is not explicitly pointed out that they are dp and both classes are directly derived from java.lang.Object, one can only conclude that it must be "normal" pixels.
If, for some reason, you need to convert from dp to px and vice versa, have a look at this document:
http://developer.android.com/intl/es/guide/practices/screens_support.html
It uses pixels, not density independent pixels.
It using pixel but if you want must convert it.
private int convertDpToPx(int dp){
return Math.round(dp * (getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
I hope it helps.
I have a circular overlay that can change according to the user's preferences: they have a circle of radius 'r' around them and a slider can change 'r' accordingly. So far it works perfectly well.
My problem is I don't know how to find the proper conversion from the circle's radius to the map's metric. As an example, given the circle below, what is the distance covered with the given radius?
You must know what is the scale of the map you are showing. Having scale of the map you could convert pixels size to metric size. And having this proportion you can convert radius given in pixels to meters.
So here's how you do it...
Jedil is correct you have to find your screen width/height, the dpi of the screen, etc. So, looking through this old osmdroid source I sorta figured out this:
//Get the x and y dpi
this.xdpi = this.context.getResources().getDisplayMetrics().xdpi;
this.ydpi = this.context.getResources().getDisplayMetrics().ydpi;
//Get the screen width/height
this.screenWidth = this.context.getResources().getDisplayMetrics().widthPixels;
this.screenHeight = this.context.getResources().getDisplayMetrics().heightPixels;
// DPI corrections for specific models
String manufacturer = null;
try {
final Field field = android.os.Build.class.getField("MANUFACTURER");
manufacturer = (String) field.get(null);
} catch (final Exception ignore) {
}
if ("motorola".equals(manufacturer) && "DROIDX".equals(android.os.Build.MODEL)) {
// If the screen is rotated, flip the x and y dpi values
WindowManager windowManager = (WindowManager) this.context
.getSystemService(Context.WINDOW_SERVICE);
if (windowManager.getDefaultDisplay().getOrientation() > 0) {
this.xdpi = (float) (this.screenWidth / 3.75);
this.ydpi = (float) (this.screenHeight / 2.1);
} else {
this.xdpi = (float) (this.screenWidth / 2.1);
this.ydpi = (float) (this.screenHeight / 3.75);
}
} else if ("motorola".equals(manufacturer) && "Droid".equals(android.os.Build.MODEL)) {
// http://www.mail-archive.com/android-developers#googlegroups.com/msg109497.html
this.xdpi = 264;
this.ydpi = 264;
}
// set default max length to 1 inch
maxLength = 2.54f;
That's how you get the 'constants' (at least in the device's eyes). To convert...
// calculate dots per centimeter
int xdpcm = (int) ((float) xdpi / 2.54);
int ydpcm = (int) ((float) ydpi / 2.54);
// get length in pixel
int xLen = (int) (maxLength * xdpcm);
int yLen = (int) (maxLength * ydpcm);
// Two points, xLen apart, at scale bar screen location
IGeoPoint p1 = projection.fromPixels((screenWidth / 2) - (xLen / 2), yOffset);
IGeoPoint p2 = projection.fromPixels((screenWidth / 2) + (xLen / 2), yOffset);
// get distance in meters between points
final int xMeters = ((GeoPoint) p1).distanceTo(p2);
...and it's a similar, if not near-identical, matter to get the yMeters (hint: use screenHeight).
Admittedly, I'm not totally sure of what the lines IGeoPoint... are doing but I realize the conversion is there. Hoping this helps someone out in the future. For a better understanding of the above code, please see the link I've posted.
I think what you're looking for is a meters-to-pixels calculation. You can get this from the projection:
// Get projection
Projection proj = mMapView.getProjection();
// How many pixels in 100 meters for this zoom level
float pixels = proj.metersToPixels(100);
// How many meters in 100 pixels for this zoom level
float meters = 1 / proj.metersToPixels(1 / 100);
// You could also get a raw meters-per-pixels value by using TileSystem.GroundResolution()
Two things to remember - this value will change not only based on what zoom level but based on what latitude you are at on the maps.
I have posted a message before about setting the text size in pexcles. I found some post that had using the following line to set a scale facter.
final float scale = getContext().getResources().getDisplayMetrics().density;
The text was still drawn t the same size on my acer tables, and vergin mobile phone.
My vergin phone has a resultion around 320 by 400 and the tables is something like 800 by 1100..
When I traced the code with the debuuger, scale is always pne..
code listing.
paint.setColor(Color.WHITE);
final float scale = getContext().getResources().getDisplayMetrics().density;
int size = (int) (18 * scale + 0.5f);
paint.setTextSize(18); // cGlobals.TranslateX
canvas.drawText("SETTINGS:", cGlobals.TranslateX(900),cGlobals.TranslateY(150), paint);
Try this below code..
final int scale = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
(float) 123.4, getResources().getDisplayMetrics());
I would like to have the dpi value, if the user taps the imageview on my activity.
at the moment i have set an onTouchListener, but with this listener i only get the "event.getX/Y" pixel values..
is there any way to get the dpi value? maybe something like a converter px->dpi?
EDIT:
// Converting dips to pixels
float dips = 20.0f;
float scale = getContext().getResources().getDisplayMetrics().density;
int pixels = Math.round(dips * scale);
// Converting pixels to dips
int pixels = 15;
float scale = getContext().getResources().getDisplayMetrics().density;
float dips = pixels / scale;
I have an image of a face (250px X 250px) that is in an absolute layout element. I currently get the user's touch coordinates and using some maths calculate what has been touched (eg the nose), then do something accordingly.
My question is how to scale this to fit the screen width available. If I set the image (in the xml) to fill_parent, the coordinates are way out. Can this be remedied by converting the touch coordinates to dips (if so, how), or will I need to get the screen width (again convert into dips) and sort out the coordinate problem using more maths?
Any and all help appreciated.
pixels = dps * (density / 160)
The (density / 160) factor is known as the density scale factor, and get be retrieved in Java from the Display Metrics object. What you should do is store the position of the nose etc in terms of dips (which are the same as pixels on a screen with density 160), and then convert dips to pixels depending on what screen you are running on:
final static int NOSE_POSITION_DP = 10;
final float scale = getContext().getResources().getDisplayMetrics().density;
final int nosePositionPixels = (int) (NOSE_POSITION_DP * scale + 0.5f);
I have three useful functions in my library...
get Screen Density
public static float getDensity(Context context){
float scale = context.getResources().getDisplayMetrics().density;
return scale;
}
convert Dip to Pixels.
public static int convertDiptoPix(int dip){
float scale = getDensity();
return (int) (dip * scale + 0.5f);
}
convert Pixels to Dips.
public static int convertPixtoDip(int pixel){
float scale = getDensity();
return (int)((pixel - 0.5f)/scale);
}
A very simple way of doing this.
int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 250, (mContext).getResources().getDisplayMetrics());
public int getDip(int pixel)
{
float scale = getBaseContext().getResources().getDisplayMetrics().density;
return (int) (pixel * scale + 0.5f);
}