Android: Convert points to pixels - android

I have been using the pt unit in XML files. Now I need to set the width of an element at runtime. How can I set the width by points so that it is the same unit I have been using everywhere else. I assume I will need to multiply by resolution and dpi. A code sample would be best.

First you should really read the following in-depth article from the Android Developer Documentation :
http://developer.android.com/guide/practices/screens_support.html
Right in the middle you'll find the following under the title :
Do not use hard-coded pixel values in your code
// Convert the dps to pixels
final float scale = getContext().getResources().getDisplayMetrics().density;
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);

You can use dip instead of pt

Related

animating xml elements in java code in dps (android studio)

I'm using android studio to design a game.
I used the 'dp' unit in my 'xml' file for defining my elements.
In java code, I want to move those elements by function animate() like image_button_red1.animate().xBy(first value).yBy(second value);
this function only takes float value, But the animation is different in each device.
I want to use the 'dp' unit to solve this problem.
Is there a function that takes another unit like 'dp'?
I've found an answer.
I designed my layout in pixels and when I used, for example, animate().xby(10.0f), the translation was right in each device. The equation between the pixel and dp is: px = dp * (dpi / 160);
Then I used dp instead of px and used the function Resources.getSystem().getDisplayMetrics().density to get the density of each screen which is running the code.
So I used a float variable instead of 10.0f which this value calculated from the noted equation. My object size was 360 dp, and the equation changed to px = 2.25*dpi.
And in my case, I used a variable like this:
float House_size = 2.25f * 14.44f * Resources.getSystem().getDisplayMetrics().density;
then I used animate().xby(House_size);
And now the result works properly on every single device.

Android - Google Maps - Projection - toPixels() - Is it device independent pixels?

I am using the Map View Projection to obtain the screen pixels like
currentPixelLocation = businessMapMv.getProjection().toPixels(tappedLocation, null);
Then I am using this to do some manipulation on the screen like centering a balloon tip.
So what I do is
currentPixelLocation.y = currentPixelLocation.y - 100
This works fine. Are the pixel locations returned by the toPixels method device independent ?
Will my manioulation like the above code work for all screen resolutions ?
I think there is a misunderstanding in device independent pixels on your site. If you declare your layout in device independent pixels (dip), the framework itself calculates the correct Veiw size - based on device display density - for the device it running on at runtime. After the framework calculates the View dimension, the View has its dimension set in pixels.
So therefore, getProjection().toPixels() gives you the position relative to the underlaying MapView in pixels. Those pixels are device independent.
What seems wrong to me is you calculation currentPixelLocation.y = currentPixelLocation.y - 100 What does the 100 stand for? These 100 are definately device dependent. If you want to subtract 100 pixels, just use this calculation currentPixelLocation.y = currentPixelLocation.y - 100 * getResources().getDisplayMetrics().density + 0.5f. It ensures, that the 100 pixels are calculated device *in*dependent.
They are device independent, but they depend on the tile size that is defined for the tile layer. On regular maps the default tile size is 256 x 256 pixels.

Convert mm to pixels

Does anyone have a good algorithm to convert mm to pixels on Android?
The thing is, I want to be able to set a minimum height of a View using mm as unit.
And no, I don't want to use android:minHeight in xml, this should be in the code.
Convert 1mm to pixel
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1,
getResources().getDisplayMetrics());

What kind of connection exists between innerRadiusRatio and thicknessRatio from GradientDrawable class?

Let's supposed we've got a ring with inner radius R2 and outer radius R1. According documentation:
Inner radius of the ring expressed as a ratio of the ring's width.For instance, if innerRadiusRatio=9, then the inner radius equals the ring's width divided by 9
As I understand this means that innerRadiusRatio = 2*R1 / R2.
About thicknessRatio there is that:
Thickness of the ring expressed as a ratio of the ring's width. For instance, if thicknessRatio=3, then the thickness equals the ring's width divided by 3. So thicknessRatio = 2*R1 / (R1 - R2).
From this two equationÑ– we can get this one: thicknessRatio*(1-2/innerRadiusRatio)=2 which means that there is a connection between thicknessRatio and innerRadiusRatio. But there is nothing about this connection in GradientDrawable class documentation. And it doesn't seem that there is any connections between them as I can set thicknessRatio and innerRadiusRatio which doesn't satisfying last equation.
So tell me please where I'm wrong in my consideration or what are this parameters really responsible for?
I know this is pretty late, but it may help others looking for this.
In the documentation it says:
Inner radius of the ring expressed as a ratio of the ring's width.
The ring's width is not the Radius of the ring, it is the width of the view containing the ring. I draw this for an easier explanation:
That's the scheme of a view with a ring inside. The letters mean:
W: Width
P: Padding
Th: Thickness
Ir: Inner Radius.
And I will add:
R: Radius.
IRR: InnerRadiusRatio.
THR: ThicknesRatio.
The documentation actually describes the following relationship:
Ir = W/IRR
Th = W/THR
So you can actually calculate the Radius.
R = Ir + Th = W (1/IRR + 1/THR).
You can prove this by creating a view with a Ring that has:
InnerRadiusRatio="4"
ThicknessRatio="4".
This will create a ring that has exactly the same width as the view.
Note: All of the previous formulas are calculated with no padding. If there is padding on the View, you should replace every W with (W - P).
Ratios are a comparison of two numbers, so the above two equations can be rewritten as
Ratio1 = InnerRadius : Ring Width (where Ratio1 = InnerRadiusRatio)
Ratio2 = Thickness : Ring Width (where Ratio2 = ThicknessRatio)
Which means...
Ring Width = Ratio1 x Inner Radius = Ratio2 x Thickness
The "2" appeared since you added it into your equation. The only common denominator in all equation is "Ring Width". Trying it out with real numbers helps too.

Custom rendered Android app widget

I'm making an app widget for Android, which due to being composed of custom elements such as graphs, must be rendered as a bitmap.
However, I've run into a few snags in the process.
1) Is there any way to find the maximum available space for an app widget? (OR: Is it possible to calculate the dimensions correctly for the minimum space available in WVGA (or similar wide) cases?
I don't know how to calculate the maximum available space for an app widget. With a conventional app widget it is possible to fill_parent, and all the space will be used. However, when rendering the widget as a bitmap, and to avoid stretching, the correct dimensions must be calculated. The documentation outlines how to calculate the minimum dimensions, but for cases such as WVGA, there will be unused space in landscape mode - causing the widget to look shorter than other widgets which stretch naturally.
float density = getResources().getDisplayMetrics().density;
int cx = ((int)Math.ceil(appWidgetInfo.minWidth / density) + 2) / 74;
int cy = ((int)Math.ceil(appWidgetInfo.minHeight / density) + 2) / 74;
int portraitWidth = (int)Math.round((80.0f * cx - 2.0f) * density);
int portraitHeight = (int)Math.round((100.0f * cy - 2.0f) * density);
int landscapeWidth = (int)Math.round((106.0f * cx - 2.0f) * density);
int landscapeHeight = (int)Math.round((74.0f * cy - 2.0f) * density);
Calculating cx and cy gives the number of horizontal and vertical cells. Subtracting - 2 from the calculated dpi (e.g. 74 * cy - 2) is to avoid cases where the resulting number of pixels is rounded down. (For example in landscape mode on Nexus One, the height is 110, not 111 (74 * 1.5).
2) When assigning a bitmap to an ImageView which is used as part of the RemoteViews to view the image, there are 2 methods:
2.1) By using setImageViewUri, and saving the bitmap to a PNG file. The image is then served using an openFile() implementation in a ContentProvider:
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException
// Code to set up imageFileName
File file = new File(getContext().getCacheDir(), imageFileName);
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
This works, and it's the approach I'm currently using. However, if I set the scaleType of the ImageView to "center", which by the documentation is supposed to "Center the image in the view, but perform no scaling.", the image is incorrectly scaled. Setting the density of the bitmap to DENSITY_NONE or getResources().getDisplayMetrics().densityDpi doesn't make any difference when saving the bitmap to PNG, it seems to be ignored when the file is loaded by the ImageView. The result is that the image is scaled down, due to some dpi issue. This seems to describe the case:
http://code.google.com/p/android/issues/detail?id=6957&can=1&q=widget%20size&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
Because it is not possible to use scaleType:center, the only way I've found to work is to set the layout_width and layout_height of the ImageView statically to a given number of dpis, then rendering the bitmap to the same dpi. This requires the use of scaleType:fitXY. This approach works, but it is a very static setup - and it will not work for resizable 3.1 app widgets (I haven't tested this yet, but unless onUpdate() is called on each resize, this is true).
Is there any way to load an image to an ImageView unscaled, or is this impossible due to a bug in the framework?
2.1) By using setImageViewBitmap directly. Using this method with the Bitmap.DENSITY_NONE setting on the bitmap, the image can be shown without scaling correctly. The problem with this approach is that there is a limitation to how large images can be set through the IPC mechanism:
http://groups.google.com/group/android-developers/browse_thread/thread/e8d84920b999291f/d12eb1d0eaca93ac#01d5c89e5e7b4060
(not allowed more links)http://groups.google.com/group/android-developers/browse_thread/thread/b11550601e6b1dd3#4bef4fa8908f7e6a
I attempting a bit of a hack to get past this issue, by splitting the widget into a matrix of images which could be set in 100x100 pixel blocks. This did allow for larger widgets to work, but ended up being very heavy and failed on large widgets (4x4).
Sorry for a very long post. I've tried to explain a few of the different issues when attempting to use a bitmap rendered app widget. If anyone has attempted the same and have found any more solutions to these issues, or have any helpful comments, this will be highly appreciated.
An approach that worked for us for a similar situation was to generate our graph as a 9-patch png, with the actual graph part as the scalable central rectangle, and the caption text and indication icons (which we did not want all stretched out of shape) and border effects, placed on the outer rectangles of the image.

Categories

Resources