DataBinding: Как получить ресурс по динамическому идентификатору?

Я знаю, что можно ссылаться на ресурсы в макете по их идентификатору ресурса:

android:text="@{@string/resourceName}"

Однако я хотел бы ссылаться на ресурс по id, который известен только во время выполнения. В качестве простого примера предположим, что у нас есть такая модель:

public class MyPOJO {

    public final int resourceId = R.string.helloWorld;

}

И теперь мне нужно использовать это значение как значение в строке формата. Позвольте называть его

<string name"myFormatString">Value is: %s</string>

Самый простой подход не работает:

android:text="@{@string/myFormatString(myPojo.resourceId)}

Это просто поместит целочисленное значение в placeholder (также это доказывает, что я правильно инициализировал POJO, поэтому я не предоставляю весь макет здесь).

Я также попытался использовать @BindingConversion, но он не сработал (что на самом деле ожидается, но я все равно пытался) - int по-прежнему был назначен методу замещения и привязки.

Как я могу явно получить ресурс по этому id в библиотеке DataBinding?

Ответы

Ответ 1

Я создал свой собственный метод:

public class BindingUtils {

    public static String string(int resourceId) {
        return MyApplication
                .getApplication()
                .getResources()
                .getString(resourceId);
    }

}

Объявление импорта для него:

<data>

    <import type="com.example.BindingUtils" />

    ...

</data>

И просто вызывая его во время привязки:

android:text="@{@string/myFormatString(BindingUtils.string(myPojo.resourceId))}"

Было бы неплохо иметь готовый метод для этого. DataBinding - это sitll в бета-версии, поэтому, возможно, это произойдет в будущем.

Ответ 2

Другим решением является создание для него пользовательского @BindingAdapter.

@BindingAdapter({"format", "argId"})
public static void setFormattedText(TextView textView, String format, int argId){
    if(argId == 0) return;
    textView.setText(String.format(format, textView.getResources().getString(argId)));
}

А затем просто укажите переменные отдельно.

<TextView
    app:format="@{@string/myFormatString}"
    app:argId="@{myPojo.resourceId}"

Вы можете использовать массив, если вам нужно несколько аргументов, но в моем случае этого было достаточно.

Ответ 3

По состоянию на июнь 2016 года это возможно в XML:

android:text= "@{String.format(@string/my_format_string, myPojo.resourceId)}"

Ответ 4

Вы можете использовать:

android:text='@{(id > 0) ? context.getString(id) : ""}'