Android positioning in pixels works but shouldn't - java

I've been positioning things (bitmaps, text) on a surface view using pixels. For example, to centre something I would take half of the width and height of the rectangle representing the screen. Screen width and height are being returned as expected. My phone (480*800) is reporting the available screen as 442*800, with density 1.5, and running on a 240*320 emulator the available screen is reported as 221*320, density 0.75. All as expected.
But these values, surely, are pixels, and so surely to centre something I should first multiply by the density factor before halving. The strange thing is everything is centred perfectly, on both the low res emulator and my high res phone. This doesn't make sense to me.
On both screens, in order to get text to appear the same, I set the size using a density scaled value, as I'd expect, and this works.
In the manifest I've declared support for all screen sizes (although I was seeing the same 'correct' behaviour before I did this as well)
Why are the pixel values 'working' without me adjusting them for density? I'm now very confused.

A pixel is a pixel is a pixel!
It is the lowest common denominator of screens and sizes.
Density is how many pixels are packed into a unit of measure, typically an inch. on a physical display.
For example, taking a physical width of 5 inches, with a resolution of 500x1000 yields a density of 200dpi (1000 pixels in 5 inches). A physical width of 4 inches with the same resolution yields a density of 250dpi (1000 pixels in 4 inches).
x=500 (half the width) is the centre of the screen on both and is independent of density. Indeed, half the width in pixels is the centre of the screen for any size screen at any density.

Related

Android - Can't draw same size square on all devices

I have an application running on android on which I have to draw a grid. I would like the cells of the grid to be of the same size on all devices, and I've found this method to do that:
float scale = getResources().getDisplayMetrics().density;
float SIZE = DESIRED_DP_VALUE * scale + 0.5f;
DESIRED_DP_VALUE is a value I set for the cells dimension.
I've tried the app on two smartphones and a tablet: the tablet and one of the smartphones have the cells of the same size, while the other smartphone doesn't.
This is the method I use to draw the grid:
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
int count=0;
while(count<=row){
float coordinate=count*SIZE;
canvas.drawLine(coordinate,0,coordinate,column*SIZE,whitePaint);
count++;
}
count=0;
while(count<=column){
float coordinate=count*SIZE;
canvas.drawLine(0,coordinate,row*SIZE,coordinate,whitePaint);
count++;
}
}
The grid is draw correctly on each device.
Where could the problem be?
I think you are mixing some concepts.
The size in pixels is that, how many dots are counting per with or height.
Every device has its own screen size measured in inches and the amount of pixels or dots able to draw in width and height.
The relationship between dimension and pixels is the density.
So, what do you want to do?
Draw an square which shows the same physical size on the screen or a square with the same amount of pixels?
If you want to draw based on inches, take it that way.
For drawing an one inch square, for a device with a density of 300 pixels per inch you need 300 pixels.
If the device is 150 pixels per inch, you must draw a 150 pixels square.
So, you need to keep fixed the size in inches, not the desired DP.

How meters to pixel and scaling works in Box2d?

This is my first time using Box2d with Libgdx and I'm confused because now I'm dealing with meters and not pixels, for example if I wan't to set the size of my shape to 80x80 pixels, how do I do that in meters? Obviously I would have to zoom the camera which I have no idea how to do it. I wan't to know how can you set the amount of pixels needed to have one meter.

Java - I need help understanding UI scaling to different screen sizes

I am creating an Android app and want to know how to scale my images, buttons, etc. to fit the screen size. I am drawing my objects using RectF's and Canvas. I am running my screens through the View class and am not using XML. I have already posted on here but I am still very stuck on this issue and it is disabling me from releasing my app. If someone could give me some quick instruction over skype or teamview I would be so happy!
Thanks guys :)
EDIT
titleBounds.set(screenWidth / 2 - screenWidth * 1/3 * density, 50 * density, screenWidth - titleBounds.left * density, titleBounds.top + screenHeight * 1/8 * density);
This is my rectF, I just want it to sit top middle on the home screen.
The density of a screen is determined by the amount of pixels and the physical size. A low density screen means there are not very many pixels per physical inch of screen. So something like a tablet, because of the big physical size, might have a low pixel density. New phones on the other hand, have a high number of pixels and yet a relatively small size screen, giving them a very high density.
You'll need to multiply your RectF values by the screen density, which will give you buttons etc that are approximately the same physical size across all screens. The screen density is a float value ranging from 0.75 (low density) to 4 (very very high density).
So if your button is about 1 inch wide on a phone, using the density multiplier will give you a button that is about 1 inch wide on a tablet as well.
You can get a density multiplier from the DisplayMetrics class:
http://developer.android.com/reference/android/util/DisplayMetrics.html#density
You get the DisplayMetrics from the context resources:
getResources().getDisplayMetrics()
So your RectF would then be created as:
float density=getResources().getDisplayMetrics().density;
RectF bounds=new RectF(left*density, top*density, right*density, bottom*density);
There's a whole lot of information on density here:
getting the screen density programmatically in android?

How to detect the zoom factor of an image

I read the related question on this topic here: How to detect subjective image quality
I would like to detect whether the uploaded image by the user could be zoomed in at high % (say, 500%) and still be or good image quality. I understand that "good image quality" is subjective, but for my purpose I would say it means "whether the image is pixelated?". I'm trying to find ways of how to do that?
Should I calculate the size of the uploaded image? Higher the size, more zoomed in it can be?
Should I calculate the total pixel count of the image?
Should I read the metatags of the uploaded image?
Combination of multiple things?
Are there solutions/libraries out there that determine the bad pixelation of an image?
Use the horizontal and vertical pixel count.
As long as the image has more pixels than you're displaying, you can zoom. Once you have more display pixels than image pixels, you have to interpolate the pixels. The higher the interpolation, the blurrier the picture.
Say you have a 4000 x 3000 pixel picture, and you're displaying 640 x 480 pixels.
You can zoom up to 625% horizontally (4000 / 640) and 625% vertically (3000 / 480). The smaller zoom number would be 625%. Rounding to an even zoom number, this picture could be zoomed up to 600% without pixelation.
Now, you could zoom even higher than 600%, if you're willing to interpolate the pixels. How high can you zoom? That would depend on what you consider acceptable interpolation.
My guess would be 25% higher. For this example picture, you could go to 800% before the picture got too blurry.
If you want to be on the safe side, keep it below the calculated zoom size. If not, go as high as you wish and let the user determine how high is too high.

How to convert pixels to dp?

I am trying to create a simple android app in Java but I have hit a bump in the road.
I have an Array List that contains many Bitmaps and I am drawing them to the canvas but I am using the measurement of pixels and that doesn't come out right on most devices.
So is there any way to find out the size of my Graphic in dp and scale it to the screen density/size with dp and position it with dp or dip.
My Graphics ( Squares ) :
Graphic size in ldpi = 50px
Graphic size in mdpi = 75px
Graphic size in hdpi = 100px
Everyting else in the code is fine apart from it comes out looking weird?
Any help would be appreciated.
James.
From the android developer doc:
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
see this for more info.
/**
* Convert dp in pixels
* #param dp
* #return
*/
public int getPx(int dp){
float scale = getResources().getDisplayMetrics().density;
return((int) (dp * scale + 0.5f));
}

Categories