LoginSignup
3
0

More than 3 years have passed since last update.

Android Navigation Componentのツールバーのタイトル挿入機能の内部実装について調べてみた

Posted at

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();
}

NavDestination

ではR.styleable.Navigator_android_labelを探してみると、
こちらはコンパイル時にスネークケースに置き換えられる名前で定義されている場所は、

<declare-styleable name="Navigator">
    <attr name="android:id"/>
    <attr name="android:label" />
</declare-styleable>

attrs

の箇所になります。

以上からnavGraphのxml上のandroid:labelにR.stringのリソースを連結できる仕組みになっていなかったため、
変数を埋め込んだタイトルを多言語対応させるには、
1. 遷移前の画面であらかじめgetString(int resId, Object... formatArgs)でタイトルを作りlabelを丸ごと変数にする
2. 変数を埋め込む画面のnavGraphだけNestedNavGraphで別ファイルにして固定文字列部分を各ファイルで実装する

になるかと思います。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0