2011年2月4日金曜日

【Android】【スニペット】画面密度から画像等々をどれだけスケールさせたらいいかをコード上で取得する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
画面密度が異なると、dipで表現した長さが異なります。
この仕組によって大きなスクリーン(高密度)、小さなスクリーン(低密度)でも概ね比率が損なわれる事なくコンポーネント等をレイアウトできます。
ところがこの便利なdipの表現がコード上で動的にできません。(多分)
layout.xmlでは出来るんでまーいいんですが、たまーに動的にやりたい気分の時もあります。
どーしたらいいかというと、DisplayMetricsという画面の情報を持っているクラスのscaledDensityを使います。
scaledDensityには画面密度に対するpxの倍率が入ってます。
だいたい高密度のhdpiの端末(Desire,Nexsus系,IS03とか、GalaxySとか)は1.5が入ってます。
100pxのボタンがあったとしたら、150pxすると比率的にいいという事になります。
480x320(mdpi)の場合scaledDensity=1で100pxは幅の31.25%
800x480(hdpi)の場合scaledDensity=1.5で150pxは幅の31.25%!
とまぁscaledDensityで大体同じ比率のレイアウトが出来るんですね~

で,そのscaledDensity。取得が結構面倒です。
scaledDensityが取りたいからってあちこちのコードで取り出してたら面倒なんで、スニペット作りました。
以下のstaticメソッドをどっかに書いておけばいつでもscaledDensityが取り出せます。
public static float getDisplayScale(Context context){
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
return dm.scaledDensity;
}

使った結果はこんなん。若干分かりにくいですが画面幅に対して大体同じ大きさになってますね。
100px*100pxの画像をBitmapで読み込んでスケールして出してます。

480x320(mdpi)













800x480(hdpi)













※ただ800x480の癖にmdpiでscaledDensityが1の不届きな端末もあります。その場合表示が腐りますのでご注意下さい。
コードはこんな感じ
ImageView imgView = (ImageView)findViewById(R.id.img);
Bitmap img = BitmapFactory.decodeResource(getResources(), R.drawable.data);
Matrix m = new Matrix();
float scale = getDisplayScale(this);
m.setScale(scale, scale);
Bitmap scaleImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), m, false);
imgView.setImageBitmap(scaleImg);