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.
Related
I know this might be a silly question but I have really gone through so many materiel and links but still not quite understand it. In the "Supporting Multiple Screens" section of Android Develop Doc, it introduces dp like this:
Density-independent pixel (dp)
A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way. The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.
Basically I understand the fact that screen with higher dpi would have more pixels in a single physical inch, which means a dp in such a screen would equal more physical pixels(px).
But according to the above conversion equation (in bold font), in a screen with higher dpi (e.g. 240 dpi screen) , a px = (240 / 160) * dp = 1.5dp. This seems to mean that in higher dpi screen a px would equal more dp. This looks in conflict with my previous understanding.
So, please, could anyone help me to figure this tricky issue out. Thank you a lot, really.
You are looking at the wrong place in the formula. To see how many dp equals one px in different density, lets rearrange the formula:
px = dp * (dpi/160)
dp = px / (dpi/160)
Now for 1px, in mdpi devices:
dp = 1 / (160/160) = 1dp
In hdpi devices:
dp = 1 / (240/160) = 0.666666667dp
You can see that 1px equals less dp in higher density devices
I'm testing on a Samsung Galaxy Note 3 which according to the docs is 1080 x 1920 pixels (~386 ppi pixel density). I want to figure out what the screen width in dp is so I can properly apply and check the new size qualifiers.
I've measured the screen width (in portrait) with a good 'ole ruler = 71mm = 2.8 inches
1080 / 2.8 = 386 ppi. Great, this matches the stated density.
I'm trying to figure out how many dp units the screen is wide.
dp = px / (dpi / 160) from here
= 1080 / (386 / 160) = 1080 /
2.4125 = 447.7 dp
So if I do this:
<TextView
android:id="#+id/density_test"
android:layout_width="447dp"
android:layout_height="wrap_content"
android:background="#ffff0000"
android:text="DENSITY TEST 447dp" />
then on my Galaxy Note 3 this view should be almost exactly the width of the screen. But it isn't, it's way wider.
So I set the above view to layout_width="300dp", measured how wide it was with my ruler and extrapolated the actual screen width in dp, based on this test:
300dp = 59mm
Total screen width is 71mm
so extrapolating screen width in dp = (71 / 59) * 300 = 361dp
361dp != 447.7dp
What is going on here? I feel like I must be doing something dumb.
Edit: I tried putting the layout file inside /res/layout-xhdpi but it had no effect. I thought maybe it was scaling it by xhdpi / mdpi since I had the xml in the default /res/layout dir.
The actual pixel size is calculated based on dp, but not as accurate as the formula dp = px / (dpi / 160) does. Indeed, it first determines the screen density (ldpp, mdph, hdpi, xhdpi, xxhdpi, xxxhdpi) and using that density to get one ratio from {0.75, 1.0, 1.5, 2.0, 3.0, (4.0)}.
In you case, the system deems 386dpi as xxhdpi, so it calculates the value by multiplying 3.0, and 360dp would exactly fill the width of your screen (1080p)
I'm new in designing the layouts. I am getting the bitmap from the server and I'm setting the imageview height such that it look good on every density either ldpi, mdpi, hdpi, xhdpi.
stripImageView.getLayoutParams().height = (int) ((Util.screenWidth(this) * strip.getHeight() / strip.getWidth()) * getResources().getDisplayMetrics().density);
But This code not working for me. Some device images looking very small and Some device it look fine
Try just setting the dimensions in your layout using dp instead of px. Dp (or dip) stands for density independent pixels and will automatically scale based on density.
EDIT: another issue I see is that you're referencing both the screen width and height so your screen aspect ratio would also affect that calculation.
convert them to DIP:
stripImageView.getLayoutParams(). height =
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, <HEIGHT>,
getResources().getDisplayMetrics());
where HEIGHT is the height in px you want. You could base it off the strip height or something.
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.
In Android when Im measuring, is it wise to use DP, or something else? Im scared that dp might change from device to device and my app will look horrible in anything other than my phone.
You should ALWAYS use dp. If you need the value in pixels, you could use this method -
public static int dpToPixels(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
always use dip
density independant pixel
If you look at the reference documentation you'll see that's the point of dp. Specifically,
The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.
So unless you want to be limited to a single screen size and density, always use dp.
Qasim, dp or dip was invented to prevent what your afraid of. Check out this article: http://developer.android.com/guide/practices/screens_support.html, as well as this other question: What is the difference between "px", "dp", "dip" and "sp" on Android?
In addition to dp, you may also use pt (point = 1/72 of an inch), in (inch) and mm (millimeter).
Since all of these units are based on actual physical size, your UI elements will retain the same physical size on any device.