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
Related
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 have a SurfaceView and TextView on which I drawing a text
Paint p = new Paint();
p.p.setTextSize(14);
canvas.drawText(....
TextView text =...
text.setTextSize(14);
On some devices both texts looks absolutely the same. But on an emulator and Samsung Galaxy III the text on canvas is twice smaller. Why? How to get same size on all devices?
The SurfaceView and TextView are on the screen in the same time. The TextView lay on several Layers and overlaid on Canvas of SurcafeView.
Best Regards
You must make use of Device independent Pixels(dp/dip) in android to get same size on all devices. In case of Text there is scale-independent pixels(sp). check out more about these for better understanding.
To convert Pixel value into dp use the following code:
public static float convertPixelsToDp(float px,Context context){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}
To convert dp value into pixel use the following code:
public static float convertDpToPixel(float dp,Context context){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float px = dp * (metrics.densityDpi/160f);
return px;
}
just call whichever method you want for your requirement.
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
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());