TextViewのテキストサイズ指定
TextViewなどのテキストサイズをJavaのコードから動的に変更しようとして、はまりそうだったのでメモ。
ちなみに今回の実行環境はAndroid 2.2 (API Level 8)を使った。この環境だとデフォルトで以下のようなAndroidManifest.xmlの設定が有効になっていることになる。
<supports-screens android:anyDensity="true" />
Android 1.6 (API Level 4)よりも低い場合はanyDensityのデフォルト値がfalseになる。anyDensityの値がfalseの場合はまた話が変わってくるので注意が必要。
このあたりの話は以下を参考に。
テキストサイズの定義と取得方法
このページのDimensionの項を見るとテキストサイズの定義とXMLファイルでの取得方法、Javaコードでの取得方法がわかる。以下のような感じ。
テキストサイズの定義
<resources> <dimen name="font_size">16sp</dimen> <resources>
XMLファイルでのテキストサイズの取得方法
@dimen/font_size
Javaコードでのテキストサイズの取得方法
Resources res = getResources();
float fontSize = res.getDimension(R.id.font_size);
試してみる
XMLファイルでの指定とJavaコードでの指定のそれぞれについて2種類のテキストサイズを指定してみる。
res/values/dimens.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="font_size_small">16sp</dimen> <dimen name="font_size_large">32sp</dimen> </resources>
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 小さいテキスト(XML指定) --> <TextView android:id="@+id/smallTextXml" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="@dimen/font_size_small" android:text="Small Text (XML)" /> <!-- 小さいテキスト(コード指定) --> <TextView android:id="@+id/smallTextCode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Small Text (Code)" /> <!-- 大きいテキスト(XML指定) --> <TextView android:id="@+id/largeTextXml" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="@dimen/font_size_large" android:text="Large Text (XML)" /> <!-- 大きいテキスト(コード指定) --> <TextView android:id="@+id/largeTextCode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Large Text (Code)" /> </LinearLayout>
XML指定と書いてあるTextViewはtextSize属性に先ほど定義したテキストサイズを指定している。コード指定と書いてあるTextViewはJavaコードからテキストサイズを指定するためここでは指定していない。
TextSizeSampleActivity.java (間違ったコード)
import android.app.Activity; import android.content.res.Resources; import android.os.Bundle; import android.widget.TextView; public class TextSizeSampleActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Resources res = getResources(); float fontSizeSmall = res.getDimension(R.dimen.font_size_small); float fontSizeLarge = res.getDimension(R.dimen.font_size_large); // 小さいテキストのテキストサイズを指定 TextView smallTextCode = (TextView) findViewById(R.id.smallTextCode); smallTextCode.setTextSize(fontSizeSmall); // 大きいテキストのテキストサイズを指定 TextView largeTextCode = (TextView) findViewById(R.id.largeTextCode); largeTextCode.setTextSize(fontSizeLarge); } }
先ほどの例にしたがってテキストサイズを取得。setTextSizeメソッドでテキストサイズを指定している。
実行結果(間違ったコード)
修正
正しいコードは以下のようになる。
TextSizeSampleActivity.java (正しいコード)
import android.app.Activity; import android.content.res.Resources; import android.os.Bundle; import android.util.TypedValue; import android.widget.TextView; public class TextSizeSampleActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Resources res = getResources(); float fontSizeSmall = res.getDimension(R.dimen.font_size_small); float fontSizeLarge = res.getDimension(R.dimen.font_size_large); // 小さいテキストのテキストサイズを設定 TextView smallTextCode = (TextView) findViewById(R.id.smallTextCode); // ※ 設定値の単位を指定するようにした smallTextCode.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSizeSmall); // 大きいテキストのテキストサイズを設定 TextView largeTextCode = (TextView) findViewById(R.id.largeTextCode); // ※ 設定値の単位を指定するようにした largeTextCode.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSizeLarge); } }
実行結果(正しいコード)
何が問題だったか
- TextView | Android Developers
- Resources | Android Developers
- platform_frameworks_base/Resources.java at master · aosp-mirror/platform_frameworks_base · GitHub
要するに
Resources res = getResources();
float fontSize = res.getDimension(R.id.font_size);
このコードで取得できるテキストサイズはpx単位なのに
TextView#setTextSize(float)
これで指定するテキストサイズがsp(scaled pixel)単位だったのが問題だった。
sp単位は160dpiを1として実際の解像度に合わせた比率で実際のpx単位を求める。なので、sp単位の値を受け取るsetTextSizeメソッドが計算済みのpx単位の値を受け取ったので大きさがずれてしまっていた。
HVGAの場合で問題がなかったのはHVGAの仮想デバイスを作成するときデフォルトで解像度が160dpiになっているためだった。