言いたいことはそれだけか

KotlinとかAndroidとかが好きです。調べたことをメモします。٩( 'ω' )و

DroidKaigi公式アプリにRTL周りのPull Request出した時にやったことまとめ

DroidKaigiお疲れ様でした!公式アプリでRTL周りのPull Requestを出したので何をしたのか備忘録のメモを残しておきます。

Issue

github.com

Pull Request

github.com

やったこと

Left / Right をgrepして適切なものに置き換え

ConstraintLayout周りとかLintで指摘してくれないものがあるのでleft / rightgrepした方がいいと思います。 grepした結果を機械的に置き換えれば良いというわけではなく、例えば情報としてはひとまとまりなんだけどviewとしては別れているみたいなケースがあります。

例えば、下記の画像の場合、

f:id:muumuumuumuu:20180214101601p:plain

What is " が一つのTextView, DroidKaigiが一つのImageVIew, " ? が一つのTextViewで構成されています。 RTL表示の場合でも英字はLTRの方向で表示するため、単純にleft / right をstart / end に置き換えてしまうと表示がおかしくなってしまいます。

上記のように色々試行錯誤した結果たどり着いたのがこちら。

具体的に書くと、DroidKaigi のImageViewの(画像自体に)左右に余白を取って、そこを起点に左右のViewに制約をつける方法で回避しました。

今気がついたんだけど、なぜか" ?の方だけRTL設定の時に? "になっちゃってますね。 What is "の方は大丈夫なんだけど。
" ?の方のTextViewにandroid:textDirection="ltr"を指定してLocaleに関係なく文字方向を固定することで回避できます。

Localeに関わらずTextViewにRTLを強制する場合は android:textAlignment を設定

例えばこのような条件の場合、

  1. アラビア語のリソースをvalues-ar配下に定義
  2. widthがmatch_parentなTextViewのtextに1のリソースを設定
  3. 端末の言語設定をアラビア語に設定

2で設定したリソースは右から表示されます。

今回のDroidKaigiの公式アプリはアラビア語リソースは用意されていないので、「開発者向けオプション」> 「RTLレウアウト方向を使用」にチェックを入れて表示確認をして行きます。この場合だと英語リソースのままレイアウト方向はRTLになりますが、逆にいうとレイアウト方向しかRTLにならないのでmatch_parentなTextViewのtextは左から表示されます。

こんな感じ。

そこでandroid:textAlignment="viewStart"を設定することでレイアウト方向とテキスト方向が連動するようになります。

directional symbolは反転させる

directional symbolって日本語でなんていうのがポピュラーなのかわかっていませんが、矢印のように方向性を持ったシンボル(そのまんまや…)のことです。Droidkaigi公式アプリではほとんどvector drawableでアイコンが作られていたので<vector>tagのなかにandroid:autoMirrored="true"を指定してやればRTL表示時に反転します。

stringsのplaceholderは(必要があれば)RTL用のものを作る

そのまんま。必要があればこんな感じでRTL用のplaceholderを作ります。

     <string name="room_format" translatable="false">%1$s%2$s</string>
     <string name="room_format_rtl" translatable="false">%2$s%1$s</string>

アラビア語のリソースを用意するのであれば不要かもしれません。ケースバイケース。
上で書いたように今回は同じ言語リソース(英語と日本語)でRTLの場合とそうでない場合に対応するのでコードで、動的にどちらを読むか判断しています。 どちらを読むかについては下記の拡張関数を作ってレイアウト方向をチェックして判断するようにしました。

fun View.isLayoutDirectionRtl() =
        resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL

コードからPadding設定するとき用に拡張関数作る

View#setPadding() メソッドは引数を4つ持ちますが、そのうち第1引数は(startではなく)left固定、第3引数も同様にright固定となります。そのため、RTL表示の場合はleftとrightを入れ替える拡張関数を作りました。

fun View.setPaddingWithLayoutDirction(start: Int, top: Int, end: Int, bottom: Int) =
        if (isLayoutDirectionRtl()) {
            setPadding(end, top, start, bottom)
        } else {
            setPadding(start, top, end, bottom)
        }

おまけ

全く気がつかなかったのですが自分のPull Requestにtypoがあって気がついた方に直してもらいました…

圧倒的申し訳なさ…!