React Native でテキストを枠内に収める方法

最近子どもがスマホのゲームでよく遊ぶので、自分でも簡単なスマホゲームを作ってあげたい気持ちに溢れている。我が子のツボはよく分かっているので(子にとっては)バチバチに面白いゲーム作れる気がするぞ。

React Native を使ってアプリを作ってみているが、フォントサイズの調整にやや困ったのでメモ。

困ったこと

React Native の利点は、1つのソースコードを書くだけでさまざまな環境で動くモバイルアプリを実装できることである。一方、環境によってはフォントサイズとレイアウトの兼ね合いが悪く、アプリの画面上の見た目が崩れることがある。

今回は、Text コンポーネントのフォントサイズをなるべく大きくしたいが、枠からはみ出ないように調整する方法を調べた。

解決策

以下のように Text コンポーネントの adjustsFontSizeToFit 属性を指定する。

    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <View style={{ width: 200, height: 30, borderColor: 'black', borderWidth: 1 }}>
        <Text style={{ fontSize: 32 }} >This is a sample message.</Text>
      </View>
      <View style={{ height: 50 }}></View>
      <View style={{ width: 200, height: 30, borderColor: 'black', borderWidth: 1 }}>
        <Text style={{ fontSize: 32 }} adjustsFontSizeToFit>This is a sample message.</Text>
      </View>
    </View>

このサンプルコードの実行結果は以下のようになる。

上にある Text コンポーネントではテキストが枠からはみ出してしまっているが、下にある Text コンポーネントではテキスト全体が枠に収まっている(収まるようにフォントサイズが小さくなっている)。いい感じ。

ちなみに Text コンポーネントの adjustsFontSizeToFit 属性のドキュメントは こちら にある。とはいっても、

Specifies whether fonts should be scaled down automatically to fit given style constraints.

ってな説明で、与えられた制約を満たすようにフォントサイズを自動的に小さくするってだけ。具体的な実装は見ていないのでどんな環境でどのくらいいい感じにフォントサイズを調整してくれるのかはよく分からない。

応用

Text コンポーネントは numberOfLines という属性も持っていて、これでテキストを表示するときの最大行数を指定できる。これをadjustsFontSizeToFit 属性を組み合わせることで、改行しない制約のもと、枠からはみ出さないようにフォントサイズを自動調整できる。

サンプルコードは以下である。先ほどの例より長いテキストを表示する例になっている。

    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <View style={{ width: 200, height: 50, borderColor: 'black', borderWidth: 1 }}>
        <Text style={{ fontSize: 32 }} numberOfLines={1}>This is a long long long long long sample message.</Text>
      </View>
      <View style={{ height: 50 }}></View>
      <View style={{ width: 200, height: 50, borderColor: 'black', borderWidth: 1 }}>
        <Text style={{ fontSize: 32 }} adjustsFontSizeToFit>This is a long long long long long sample message.</Text>
      </View>
      <View style={{ height: 50 }}></View>
      <View style={{ width: 200, height: 50, borderColor: 'black', borderWidth: 1 }}>
        <Text style={{ fontSize: 32 }} adjustsFontSizeToFit numberOfLines={1}>This is a long long long long long sample message.</Text>
      </View>
    </View>

このサンプルコードの実行結果は以下である。

上の Text コンポーネントは特に何も指定していないのでテキストがはみ出ている。真ん中は adjustsFontSizeToFit だけが指定されており、今回は改行すれば枠に収まるので2行で表示されている。最後に、下の Text コンポーネントは numberOfLines 属性が1、つまり最大1行で表示するように指定されているのでフォントサイズをかなり小さくして1行で表示されている。この例ではフォントサイズが小さすぎだが、改行するよりフォントサイズが小さくなったほうがマシというケースは多々あるだろう。

おしまい。

参考:

stackoverflow.com