ToolBarにsetTitle時に変数を挿入できる。。じゃあ変数以外の部分の多言語化は?
実際に挿入している箇所は下記のコードブロックに抜き出してある通り、
labelというCharSequence型の変数に
Pattern fillInPattern = Pattern.compile("\\{(.+?)\\}");
の
正規表現にマッチする文字が無くなるまでループを回して、
StringBuffer title = new StringBuffer();
に連結していき
最終的な文字列をsetTitle(title);
しています。
CharSequence label = destination.getLabel();
if (!TextUtils.isEmpty(label)) {
// Fill in the data pattern with the args to build a valid URI
StringBuffer title = new StringBuffer();
Pattern fillInPattern = Pattern.compile("\\{(.+?)\\}");
Matcher matcher = fillInPattern.matcher(label);
while (matcher.find()) {
String argName = matcher.group(1);
if (arguments != null && arguments.containsKey(argName)) {
matcher.appendReplacement(title, "");
//noinspection ConstantConditions
title.append(arguments.get(argName).toString());
} else {
throw new IllegalArgumentException("Could not find " + argName + " in "
+ arguments + " to fill label " + label);
}
}
matcher.appendTail(title);
setTitle(title);
}
AbstractAppBarOnDestinationChangedListener
ではlabelをどこで作っているか調べてみると、
下記のコードブロックにある通り
setLabel(a.getText(R.styleable.Navigator_android_label));
という関数でxmlから呼び出しています。
@CallSuper
public void onInflate(@NonNull Context context, @NonNull AttributeSet attrs) {
final TypedArray a = context.getResources().obtainAttributes(attrs,
R.styleable.Navigator);
setId(a.getResourceId(R.styleable.Navigator_android_id, 0));
mIdName = getDisplayName(context, mId);
setLabel(a.getText(R.styleable.Navigator_android_label));
a.recycle();
}
ではR.styleable.Navigator_android_label
を探してみると、
こちらはコンパイル時にスネークケースに置き換えられる名前で定義されている場所は、
<declare-styleable name="Navigator">
<attr name="android:id"/>
<attr name="android:label" />
</declare-styleable>
の箇所になります。
以上からnavGraphのxml上のandroid:labelにR.stringのリソースを連結できる仕組みになっていなかったため、
変数を埋め込んだタイトルを多言語対応させるには、
1. 遷移前の画面であらかじめgetString(int resId, Object... formatArgs)
でタイトルを作りlabelを丸ごと変数にする
2. 変数を埋め込む画面のnavGraphだけNestedNavGraphで別ファイルにして固定文字列部分を各ファイルで実装する
になるかと思います。