When I tried same text size on top different resolution bitmaps on a canvas. Same text size looked small on a bigger resolution and bigger on a small resolution image. Please Help me understand this.
You need to set proper text size for your Paint, that accounts for density. Paint.setTextSize(float), takes in a float value. You need to ensure that this is not a constant value, but one that accounts for density.
How to get the density? You get that information from DisplayMetrics.scaledDensity or DisplayMetrics.density. Once you have this value, multiply this with the fontSize and set that value as the text size. Somthing like the below.
Paint.setTextSize(density * 10f);
This way a text with 10f font size will look the same in all devices with varying densities. You can find more information on density and scaledDensity here: http://developer.android.com/reference/android/util/DisplayMetrics.html#scaledDensity
This is way you can make all text uniform size in all device.
canvas.drawText(hourText, getPx(TEXT_SIZE, activity), getPx(TEXT_SIZE / 3, activity), nPaint);
public static int getPx(int dp, Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
float logicalDensity = metrics.density;
return (int) Math.ceil(dp * logicalDensity);
}
Related
I have a textView in another view.
I want to calculate in runtime the actual display size of that text
and of its container.
If the text is too big to fit in the view I have few shorted text content alternatives.
I have read the textView doc, but it only shows [setTextSize][1]
how can i get the text size (in dp I guess ?) according to the actual screen.
(orientation, screen size, font size and so on)
TextView actually has a getTextSize() method, which returns the font size in pixels for you. You can check here the documentation. Of course this pixel value will vary accordingly to the screen density of the device. If you want to convert that value for dp or sp on runtime, you can do the following:
Pixels for SP:
float sp = px / getResources().getDisplayMetrics().scaledDensity;
Pixels for DP:
float dp = px / getResources().getDisplayMetrics().densityDpi;
if a Custom View of size 500w*600h in dp , remain same as px in (1152w*720h)px screens of android , then what will be view's size in dp and px on screen of (480w*600h)px screens. And how to calculate for different size of View.
The dp / px ratio is based on the density of the screen of the device.
I would encourage you to read the Android docs on the subject.
http://developer.android.com/guide/practices/screens_support.html
Each classification of screen density has a specific px multiplier associated with it i.e. mdpi = px * 1 and hdpi = px * 1.5
Here is a nice little calculator to help you make sense of it:
http://labs.rampinteractive.co.uk/android_dp_px_calculator/
Assuming that you specified your view sizes in dp(same as dip), you can use get an instance of DisplayMetrics to convert the dp to actual pixels for your current device.
A handy function you can add to a utility class for doing conversions:
private static float dipToPixels(Context context, int dip)
{
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, metrics);
}
While we're at it, what is the Android equivalent of [UIScreen mainScreen].scale?
Are the following equations correct?
[UIScreen mainScreen].bounds.size.width = displayMetrics.widthPixels
[UIScreen mainScreen].scale = displayMetrics.density
where you get displayMetrics like so:
DisplayMetrics displayMetrics = new DisplayMetrics();
Display display = ((WindowManager) someContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
display.getMetrics(displayMetrics);
The thing is that I'm confused by the wording for iOS versus Android.
The definitions for those UIScreen values are these:
bounds
Contains the bounding rectangle of the screen, measured in points.
(read-only)
scale
The natural scale factor associated with the screen. (read-only)
#property(nonatomic, readonly) CGFloat scale
Discussion
This value reflects the scale factor needed to convert from the
default logical coordinate space into the device coordinate space of
this screen. The default logical coordinate space is measured using
points, where one point is approximately equal to 1/160th of an inch.
If a device’s screen has a reasonably similar pixel density, the scale
factor is typically set to 1.0 so that one point maps to one pixel.
However, a screen with a significantly different pixel density may set
this property to a higher value.
I am wondering whether the width of the bounds is equivalent to the widthPixels of the DisplayMetrics and whether the scale value is equivalent to the density value on Android.
[UIScreen mainScreen].bounds.size.width = displayMetrics.widthPixels
Correct, width of the screen (display) in pixels, nothing complicated here.
[UIScreen mainScreen].scale = displayMetrics.density
Not really. They are similar values but definitely not equal.
I'll try to explain what scale is. We have iPad 1 with screen resolution 1024x768 and we have iPad 3 with double resolution (apple marketing calls it Retina) and we want applications to work on both devices. So, the application works on resolution 1024x768 (logical points) but the OS translates to physical pixels on every device using the scale (scale=1.0 on iPad 1, scale=2.0 on iPad 3).
For example, when you draw a rectangle in logical coordinates (1, 1, 20, 40), on iPad 3 it will be drawn on pixels (2, 2, 40, 80).
There are currently only two values defined: 1.0 and 2.0.
The density is a similar scaling factor but calculated differently
This is a scaling factor for the Density Independent Pixel unit, where one DIP is one pixel on an approximately 160 dpi screen
Note that again it converts logical points (called DIP on Android) into screen pixels.
The difference between iOS scale and Android density is that the logical unit is defined differently.
I use this:
private void SetScreenSizes() {
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
intScreenWidth = displaymetrics.widthPixels;
}
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 providing an option for text sizes and one of them is for the EditText boxes. I've determined the original text size using EditText#getTextSize(). The result is given in pixels. Once the user selects the text size, I use edittext.setTextSize(TypedValue.COMPLEX_UNIT_SP, chosen) to apply the text size.
Problem is different screen sizes give me wildly different text sizes, e.g. on an ICS phone, EditText.getTextSize() returns 36, which is absolutely massive and definitely not the default text size used throughout the system.
What am I doing wrong?
You are probably seeing different values due to different screen densities and the fact that the value you get from getTextSize() is in pixels(px). Density Independent Pixels(dp) and Scaled Pixels(sp) are adjusted to be independent of the screen density and they are what you should be using. To get dp or sp from px you can use a simple conversion like this:
public static float pxToDp( float px, Context context ) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / ( metrics.densityDpi / 160f );
return dp;
}
or this (which I took from this post):
public static float pixelsToSp(Context context, Float px) {
float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
return px/scaledDensity;
}