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.
Related
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
So I use Paint's measureText() method to measure the width of a segment of text, but I wanted to measure text based on a certain text size. Say I wanted to get the width of a text segment that will be 20 scaled pixels when it occupies a certain TextView. I tried the following:
Paint paint = new Paint();
paint.setTextSize(20);
paint.measureText("sample text");
However, it does not seem to be working. I believe it is returning a width with respect to a smaller text size. I feel like I'm missing something that will make me slap myself in the face and yell herp derp.
You need to get the densityMultiplier like so:
final float densityMultiplier = getContext().getResources().getDisplayMetrics().density;
final float scaledPx = 20 * densityMultiplier;
paint.setTextSize(scaledPx);
final float size = paint.measureText("sample text");
I do something like this when I have to.
int textSize = 20;
for(int i = 2; i<18 && curTextSize< textSize;i+=2)
{
this.label.setTextSize(i);
curTextSize = this.label.getPaint().measureText(this.label.getText().toString());
}
I don't have enough reputation points to comment on answers but in reference to the comments by #schwiz and #AndreasEK on the accepted answer:
measureText(), along with getTextBounds(), does not include padding so it's possible that the solution to their problem is to add the left and right padding (or start and end padding)
final float scaleFactor = getContext().getResources().getDisplayMetrics().density;
final float scaledPx = 20 * scaleFactor;
paint.setTextSize(scaledPx);
final float padding = scaleFactor * (textView.getPaddingStart() + textView.getPaddingEnd());
final float size = paint.measureText("sample text") + padding;
Try
Paint.SetLinearText(true)
That solved the problem for me.
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);
}
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