In my app I create a canvas and add some bitmaps on it. The problem is that the objects are adding why touch the screen. So on one screens they appear on the middle on different the same, but their position in pixels are different.
I mean that I got tablet and smartphone. When I touch one the object appear on both devices (multiplayer) but its not in the same place, because its passing the position by x and y.
If someone understand what I mean, can you help me?
Probably it must have something common with counting the ratio.
I am guessing the problem you are having is that the screens are different resolutions and you are passing pixel data. You will need to use dp values and before sending them convert the dp to pixel values. On the receiving device you will need to convert the pixel values being sent back to dp on the given device. Use the methods below for the conversion.
To Convert DP to Pixels:
final float scale = getResources().getDisplayMetrics().density;
int pixelValue = (int) (DESIRED_DP_VALUE * scale + 0.5f);
To Convert Pixels to DP:
final float scale = getResources().getDisplayMetrics().density;
int dpValue = (int) ((DESIRED_PIXEL_VALUE) - 0.5f / scale);
The call to getDisplayMetrics().density is what will give you a scale value based on the current device. The dp value is meant to be density independent.
How do you define the metrics? If you are using pixels, use a density independent solution:
public int GetDipsFromPixel(float pixels)
{
// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
return (int) (pixels * scale + 0.5f);
}
And use it like this in you class:
textView.setHeight(GetDipsFromPixel(50));
This way the the height of the textview will be the same dps on both devices, even if their resolution is different.
Related
I have a canvas for painting in my application and saving all the coordinate while user drawing on it. the saved coordinates are then transformed to another device and trying to plot the pixels.
like this;
(20,30),
(50,40)
..
..
..
Because of the different screen size and resolution my drawing is incomplete and positions and plotted incorrectly
how can i map the coordinate to other device which should be in exact location as that of the device where i draw the actual image.
When you save the coordinates you need to get the device independent pixels from the drawing by dividing the coordinates by the screen density and when you draw it on a device you need to multiply your coordinates by the device density. For example:
float density = getContext().getResources().getDisplayMetrics().density;
canvas.drawText(text,
xPos * density,
yPos * density,
mPaint);
Try to implement density independent pixel(dp)
The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen.
The conversion of dp units to screen pixels is simple:
px = dp * (dpi / 160).
So first determine your device dpi(dot per pixel).
So to move to (20, 30).
determine x = 20 * (dpi/160);
y = 30 * (dpi/160);
move to (x, y).
you can get dpi = getResources().getDisplayMetrics().density
my android app supports Android api 8
and I want to move an object x dpi to the left.
how can I do it?
You should transform the amount of dip to the right amount of pixels for the given screen.
This is the formula you should use:
pixels = dip * (density / 160)
the (density / 160) part is known as the density scale factor. You can get this scale factor using the following code.
float scale = getContext().getResources().getDisplayMetrics().density;
Than calculate the right amount of pixels from the given amount of dip and round it:
int pixels (int) (dip * scale + 0.5f);
In function form it would look like this.
public int getPixelFromDip(float dip){
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dip * scale + 0.5f);
}
Rolf
The developers website simply states that getHeight() will return the bitmap's height, but can someone tell me that is in pixel unit or dp unit?
It's pixel. In Java code you usually work with pixels, e.g. a view's width and height.
After Hours of Experimenting I found that it actually return height in dp units.You can verify it by changing the device screen in emulator.
bitmap.getWidth() returns width in dp unit or densitiy.
To get dpi (density per inch) for a device, use
float dpi = context.getResources().getDisplayMetrics().density;
To convert dp to px
float px = dp * dpi;
and to convert px to dp
float dp = px/dpi;
If you read on how android deals with views this not clear at all. See "Supporting Multiple Screeens". After reading that document I have come to the conclusion that "it depends." (And I'm still guessing as I have not verified my analysis.) If the View was declared with size "wrap_content", "fill_parent", or "dp" then you get "dp", otherwise you get pixels. If you used "dp" then scaling to pixels is achieved by multiplying by
getResources().getDisplayMetrics().density
For 160 dpi screen, this returns 1.0; for 320 pi screen this returns 2.0.
Dividing by getResources()....density.
I have read the "screen support API guide "(http://developer.android.com/guide/practices/screens_support.html) and much more resources, but I cannot understand how the dpi works.
I'm developing a game, and I'm not using any layouts (I'm going to draw all myself with functions like canvas.drawbitmap). But when I use the Canvas.Drawbitmap function I need to specify the pixels of the screen where I want to draw the image.
So I'm working now with a fixed resolution (1280x800) and I'm using the drawable-nodpi folder and adjusting the canvas later if the screen of the phone is wider or narrow. The problem with that is that the images look horrible when the resolution is not the native one (1280x800).
What can I do to solve this problem? I've read and read during 3 days, but all explanations and examples are related to Layouts, Nine Patches and so.
Get the density of the device being used and multiply that density by some base size that you pick (how big or small do you actually want it to be drawn?)
Example:
float objectToDrawHeight = 50; //Specified in plain pixels
float objectToDrawWidth = 50; //Specified in plain pixels
float density = getResources().getDisplayMetrics().density;
objectToDrawHeight *= density;
objectToDrawWidth *= density;
//Draw your object using the new (scaled) height and width
//If you are worried about how the object will look on different aspect ratio devices
// you can get the screen dimensions and use that ratio as a multiplier
// just as you did with density
Display display = ((Activity)context).getWindowManager().getDefaultDisplay();
float screenDimensionX = display.getWidth();
float screenDimensionY = display.getHeight();
Using density and possibly screen dimensions should allow you to draw anything and keep it scaled correctly. When using canvas, assume everything is in pixels, and that you must do the dpi conversion.
I'm doing:
button.setLayoutParams(new GridView.LayoutParams(65, 65));
According to the docs the units for the width and height (both 65 in the above) are "pixels". How do you force this to be device independent pixels, or "dp"?
You'll have to convert it from dps to pixels using the display scale factor.
final float scale = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scale + 0.5f);
I know this is an old question however I've found a much neater way of doing this conversion.
Java
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65, getResources().getDisplayMetrics());
Kotlin
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65f, resources.displayMetrics)
simplest way(and even works from api 1) that tested is:
getResources().getDimensionPixelSize(R.dimen.example_dimen);
From documentations:
Retrieve a dimensional for a particular resource ID for use as a size
in raw pixels. This is the same as getDimension(int), except the
returned value is converted to integer pixels for use as a size. A
size conversion involves rounding the base value, and ensuring that a
non-zero base value is at least one pixel in size.
Yes it rounding the value but it's not very bad(just in odd values on hdpi and ldpi devices need to add a little value when ldpi is not very common)
I tested in a xxhdpi device that converts 4dp to 16(pixels) and that is true.
Looking at your requirement, there is alternate solution as well. It seems you know the dimensions in dp at compile time, so you can add a dimen entry in the resources. Then you can query the dimen entry and it will be automatically converted to pixels in this call:
final float inPixels= mActivity.getResources().getDimension(R.dimen.dimen_entry_in_dp);
And your dimens.xml will have:
<dimen name="dimen_entry_in_dp">72dp</dimen>
Extending this idea, you can simply store the value of 1dp or 1sp as a dimen entry and query the value and use it as a multiplier. Using this approach you will insulate the code from the math stuff and rely on the library to perform the calculations.
Based on drspaceboo's solution, with Kotlin you can use an extension to convert Float to dips more easily.
fun Float.toDips() =
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, resources.displayMetrics);
Usage:
(65f).toDips()
Kotlin Version
val scale: Float = resources.displayMetrics.density
val resizedInDp = (stream.videoWidth * scale + 0.5f).toInt()
Usage:-
val params: ViewGroup.LayoutParams = yourLayout!!.layoutParams
val scale: Float = resources.displayMetrics.density
params.width = (widthDp * scale + 0.5f).toInt() // dp to px
params.height =
(heightDp * scale + 0.5f).toInt() // setting height according to aspect ratio
yourLayout!!.layoutParams = params