Jesus, for Android you must consider the pixel density of the platform to get the scaling correct. I spent a month with several different Android tablets getting a good scale calculation for all of my graphics to work properly (and pleasing) on all of the android devices, all the way from a Tattoo (tiny screen) to an Asus 10.1 inch nVidia Tegra tablet, including the Galaxy Nexus phone which has a weird pixel density and a very large resolution.
Here is what I did:
public static void ScaleTile(Drawable tile, Rect r)
{
//
// Determine an inset that preserves the aspect ratio of the tile
// but fits it into the given rectangle
//
int insetx = 0;
int insety = 0;
int dw = r.right - r.left;
int dh = r.bottom - r.top;
float tw = (float)GetDrawableWidth(tile);
float th = (float)GetDrawableHeight(tile);
float wScale = (float)dw / tw;
float hScale = (float)dh / th;
// Test the fit
float scale = 1f;
int xh = (int)(th * wScale + 0.5f);
if(xh > dh) {
// The x-scale makes the height too long, so we need to use the y-scale and adjust the width
scale = hScale;
insety = 0;
insetx = (dw - (int)((float)tw * hScale + 0.5f))/2;
}
else {
scale = wScale;
insetx = 0;
insety = (dh - (int)((float)th * wScale + 0.5f))/2;
}
// Log.d(“TILES”, “ScaleTile: rect=” + dw + “x” + dh + “, offset=” + insetx + “,” + insety + “, scale=” + scale + “, tile =” + tw + “x” + th);
r.inset(insetx,insety);
// Double-check to make sure the image fits properly into the destination rectangle.
insetx = 0;
insety = 0;
int diffx = dw - (r.right - r.left);
int diffy = dh - (r.bottom - r.top);
if(diffx < 0) {
insetx = ~~diffx;
}
else {
insetx = dw + 0.5);
}
if {
insety =~~diffy;
}
else {
insety = (int)(0.05f * (float)dh + 0.5);
}
int inset = Math.max(insetx, insety);
if(inset > 0) {
// Log.d(“TILES”, “ScaleTile: final inset =” + inset);
r.inset(inset, inset);
}
}
public static int GetDrawableHeight(Drawable d)
{
float h = (float)d.getIntrinsicHeight();
h = GameResources.GetScreenScaleFactor;
return);
}
public static int GetDrawableWidth
{
float w = d.getIntrinsicWidth;
w= GameResources.GetScreenScaleFactor();
return((int)(w + 0.5));
}
public static void SetScreenScaleFactor(Window w)
{
DisplayMetrics metrics = new DisplayMetrics();
w.getWindowManager().getDefaultDisplay().getMetrics(metrics);
// Log.d(“TILES”, “Window: xdpi=” + metrics.xdpi + “, ydpi=” + metrics.ydpi + “, font scale=” + metrics.scaledDensity + “, density=” + metrics.density + “, dpi=” + metrics.densityDpi);
//
// 320 is the reference width we used to create the UI on a 1.5 device
//
*ScaleFactor = / 320f;
*ScreenMetrics = “” + metrics.xdpi + “,” + metrics.ydpi + “,” + metrics.scaledDensity + “,” + metrics.density + “,” + metrics.densityDpi + “,” + metrics.widthPixels + “,” + metrics.heightPixels + “,” + _ScaleFactor;
}
public static float GetScreenScaleFactor()
{
return(_ScaleFactor);
}
This is in java. You should be able to read it as it doesn’t make use of any nifty Java APIs. Not sure if you can get the screen metrics for the Android device using the native API though.
On cocos2d-xna, I did something similar for the windows phone devices. They all use the NTSC format for screen resolutions, which makes it super easy to create the screen scale factors (480p, 720p, 1080p). Yeah Microsoft for standardized formats.
Android is a real nightmare. When you get it working for 2 devices, and get a third, all of a sudden it stops working … a month of trial and error and buying lots of tablets.