Androidアプリ開発のうち、気配りが重要な工程といえば「小さいエリア内での文字フォントサイズ指定」が、そのひとつに挙げられます。
一般的には「ピクセル単位」でフォントサイズをデザインされると見受けられますが、習慣的に「スケーラブルピクセル(sp)」を指定していると、ユーザーが設定アプリでフォントサイズを大きめにしていた場合、以下のような不具合が発生します。

左:フォントサイズ小、右:フォントサイズ最大
最大では、領域不足で文字やアイコンが一部見えなくなってしまいました。

ここでは以下の3つの解決方法を挙げていきます。

  1. TextViewの自動サイズ調整(参考リンク
  2. SmallestWidthなどの代替リソースを提供(参考リンク
  3. 密度非依存ピクセルを指定(参考リンク

TextViewの自動サイズ調整

Android 8.0(API Level 26)から追加された、ビューから見切れないように自動的にフォントサイズを合わせてくれる機能です。
(下位互換クラス:TextViewCompat)

<TextView
    android:id="@+id/text_you_parcent"
    android:layout_width="54dp"
    android:layout_height="41dp"
    android:layout_marginEnd="6dp"
    android:ellipsize="none"
    android:gravity="end|bottom"
    android:includeFontPadding="false"
    android:singleLine="true"
    android:text="100"
    android:textColor="@color/orange"
    android:textStyle="bold"
    app:autoSizeMaxTextSize="28sp"
    app:autoSizeMinTextSize="8sp"
    app:autoSizeTextType="uniform"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toStartOf="@id/unit_you_percent"
    app:layout_constraintStart_toEndOf="@id/icon_you"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="1" />


左:フォントサイズ小、右:フォントサイズ最大
アイコン付近の文字とパーセント値にautoSizeを適用。ビューエリアの範囲で拡大縮小されます。

一見便利ですが、注意点もあります。

  • wrap_content が機能しない(使った場合、表示結果が保証されない)
  • app:layout_constraintBaseline_toBaselineOf の制約が機能しない(%などの単位とbottomを揃えられない)

SmallestWidthなどの代替リソースを提供

例えば「layout-sw600dp」のようにリソースディレクトリを追加して、600dp未満の端末はデフォルトの「layout」ディレクトリにあるフォントサイズを小さめに設定したリソースを参照させる方法です。

<!-- 480dpi以上のフォントサイズ指定 -->
<resources>
    <dimen name="wz_percent_size">28sp</dimen>
    <dimen name="wz_caption_size">10sp</dimen>
    <dimen name="wz_name_size">16sp</dimen>
</resources>
<!-- 480dpi未満のフォントサイズ指定 -->
<resources>
    <dimen name="wz_percent_size">17sp</dimen>
    <dimen name="wz_caption_size">6sp</dimen>
    <dimen name="wz_name_size">10sp</dimen>
</resources>
<TextView
    android:id="@+id/text_you_parcent"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginEnd="2dp"
    android:gravity="end"
    android:includeFontPadding="false"
    android:singleLine="true"
    android:text="100"
    android:textColor="@color/orange"
    android:textSize="@dimen/wz_percent_size"
    android:textStyle="bold"
    app:layout_constraintBaseline_toBaselineOf="@id/unit_you_percent"
    app:layout_constraintEnd_toStartOf="@id/unit_you_percent"
    app:layout_constraintStart_toEndOf="@id/icon_you" />
左:フォントサイズ小、右:フォントサイズ最大
アイコン付近の文字とパーセント値のフォントサイズをsmallestWidthごとに分けました。
幅360dpの端末なので、デフォルトのdimens.xmlが使われます。

注意点としては、以下のようなものでしょうか。

  • リソースファイルが増えるので、その分レイアウト変更時の開発&テスト工数が増える
  • 大ざっぱに分けた場合、中間の幅の端末で中途半端な大きさで表示されるおそれがある

密度非依存ピクセルを指定

要は「android:textSize属性にdp単位で指定する」ということですが、
先に注意点として挙げますと、以下のような限定されたケースに対して使用するべきでしょうか。

  • 「アイコンの補足」といったような、優先度が高くない文言
  • もともと大きめにフォントサイズ指定された改行しない数字など
<TextView
    android:id="@+id/text_you_parcent"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginEnd="2dp"
    android:gravity="end"
    android:includeFontPadding="false"
    android:singleLine="true"
    android:text="100"
    android:textColor="@color/orange"
    android:textSize="28dp"
    android:textStyle="bold"
    app:layout_constraintBaseline_toBaselineOf="@id/unit_you_percent"
    app:layout_constraintEnd_toStartOf="@id/unit_you_percent"
    app:layout_constraintStart_toEndOf="@id/icon_you"
    tools:ignore="SpUsage" />
左:フォントサイズ小、右:フォントサイズ最大
アイコン付近の文字とパーセント値のフォントサイズを密度非依存ピクセルで指定。

Android Studioで警告がでないように tools:ignore=”SpUsage” を追加しています。
「sp と dp を間違えた」と思われないように、コメントで補足する必要があるかもしれません。

まとめ

AutoSizeも加わって、Androidのテキスト界隈もだいぶ使い勝手がよくなってきたと感じられます。
それぞれのメリットと注意点を踏まえて、スマホアプリのアクセシビリティを高めていきたいと思いました。



ギャップロを運営しているアップフロンティア株式会社では、一緒に働いてくれる仲間を随時、募集しています。 興味がある!一緒に働いてみたい!という方は下記よりご応募お待ちしております。
採用情報をみる