Android 2行以上の文字列のTextViewを中央揃えで表示し、文字列自体は左寄せにする


はい、「お前は一体何を言ってるんだ?」ってタイトルだと思います。

つまりこういうことですね。

TextViewでボタンを作るなどする場合、
TextViewにPadding(文字列とTextViewの端までの幅)を設定することがあるかと思います。
そういう時に、TextView自体は中央揃えで、中の文字列は左寄せにしたい!
ということがあります。

余裕で実装できるかと思っていたのですが実際に実装する際に少しだけ悩んだので...
同じようなことで悩んでる人のためにこちらに残しておきます。

1. layoutファイルでgravity = leftを指定してみる

こんなのlayoutファイルのTextViewのgravityでgravity = leftにすればいいだけじゃん!
と最初は思いましたが、こうなります。

activity_main.xml
<TextView
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:gravity="left"
        android:background="@color/colorPrimaryDark"
        android:textSize="15dp"
        android:textColor="@color/colorWhite"
        android:text="@string/sample_text"/>

文字列が左にずれてる・・・

2. layoutファイルでgravity = centerを指定してみる

ならgravity = centerを指定するとどうなるのか!
こうなります。

activity_main.xml
<TextView
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:gravity="center"
        android:background="@color/colorPrimaryDark"
        android:textSize="15dp"
        android:textColor="@color/colorWhite"
        android:text="@string/sample_text"/>

あたりまえですが全体が中央揃えになってしまってますね。

対策1. 文字列に全角スペースを入れて行ごとの文字数を揃え、中央揃えにする

とっても無理やりですが文字列そのものに全角スペースを入れることで、gravity = centerで実現することができました。
今回の文字列は

こんにちは!
これはサンプルアプリです!

です。
1行目の「こんにちは!」が全角6文字、2行目の「これはサンプルアプリです!」が全角13文字です。
つまり1行目の後ろに7文字分全角スペースを入れれば、1行目と2行目が同じ文字数になり、
中央揃えにすることで左寄せした状態に見える、って寸法です。

strings.xml
<string name="sample_text">"こんにちは!       \nこれはサンプルアプリです!"</string>

わかりづらいですが改行コード(\n)の前に全角スペースが7個入ってます。
全角スペースを入れる場合、文字列全体をダブルクォーテーションで囲いましょう。
そうしないとスペースを入れても画面表示する時にスペース部分が省略されてしまいます。

さて、表示はどうなるか...

activity_main.xml
<TextView
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:padding="20dp"
        android:gravity="center"
        android:background="@color/colorPrimaryDark"
        android:textSize="15dp"
        android:textColor="@color/colorWhite"
        android:text="@string/sample_text"/>

できてる!

しかし今回は2行なのでこれで済みましたが、何十行もある文字列の場合など、
全ての行に全角スペースを入れるのはめんどくさすぎてやってられないですよね。
そもそも実装の仕方に無理やり感あってすっきりしないです。

対策2. TextViewをLinearLayoutで囲う

これが一番現実的な実現方法かと思います。
TextViewをLinearLayoutで囲います。
もともとTextViewに設定していたheightやbackgroundはそのままLinearLayoutに移動します。
TextViewのheightとwidthはwrap_contentにし、文字列とTextViewのサイズを合わせます。

そして大事なのが、LinearLayoutのgravityをcenterに、TextViewのgravityをleftにします。
こうすることで、
・LinearLayoutの中のTextViewは中央揃え
・TextViewの中の文字列は左寄せ
という状態になり、実現することができます。

activity_main.xml
<LinearLayout
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimaryDark"
        android:gravity="center">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="left"
            android:padding="20dp"
            android:text="@string/sample_text"
            android:textColor="@color/colorWhite"
            android:textSize="15dp" />

    </LinearLayout>


完成!

以上です。
・全角スペースを入れて全ての行の文字数を合わせて中央寄せにする
・TextViewをLinearLayoutで囲う
2種類の解決策を紹介しました。
文字数が少ない場合は前者の方が楽に実装できますが、基本的には後者で実装したほうが綺麗かなぁと思います。

まさかこれで悩むことになるとは思いませんでした...。
同じことで悩んでいる方の助けになれば幸いです。