我知道可以通过资源ID引用布局中的资源:
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)}"
这只会将整数值放入占位符(也证明我正确地初始化了我的POJO,所以我不在这里提供整个布局)。
我也尝试使用@BindingConversion
,但它没有用(实际上是预期的,但我还是试过了) - int
仍然被分配给占位符,并且没有调用绑定方法。
如何通过DataBinding库中的id显式获取资源?
答案 0 :(得分:20)
另一种解决方案是为其创建自定义@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}"
如果你需要多个参数,你可以使用一个数组,但在我的情况下,一个就足够了。
答案 1 :(得分:14)
截至2016年6月,这可以用XML:
android:text= "@{String.format(@string/my_format_string, myPojo.resourceId)}"
答案 2 :(得分:10)
我最终创建了自己的方法:
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在测试版中也是如此 - 所以未来它可能会出现。
答案 3 :(得分:4)
另一种解决方案,如果您已经Context
,则无需导入String
类。
android:text="@{@string/myFormatString(context.getString(pojo.res))}"
将适用于
<string name="myFormatString">Value is: %s</string>
如果您的xml中没有上下文。然后按照此
<data>
<variable
name="context"
type="abc.UserActivity"/>
<variable
name="pojo"
type="abc.MyPOJO"/>
</data>
并在您的Activity
ActivityUserBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_user);
binding.setPojo(new MyPOJO());
binding.setContext(this);
答案 4 :(得分:2)
您可以使用:
android:text='@{(id > 0) ? context.getString(id) : ""}'
答案 5 :(得分:1)
您可以使用绑定适配器的官方文档中描述的automatic method selection。以下描述取自该文件:
<块引用>对于名为 example
的属性,库会自动尝试查找接受兼容类型作为参数的方法 setExample(arg)
。不考虑属性的命名空间,搜索方法时只考虑属性名称和类型。
例如,给定 android:text="@{user.name}"
表达式,库查找 setText(arg)
方法,该方法接受 user.getName()
返回的类型。如果 user.getName()
的返回类型是 String
,库会查找接受 setText()
参数的 String
方法。如果表达式返回 int
,则库搜索接受 setText()
参数的 int
方法。表达式必须返回正确的类型,必要时可以转换返回值。
考虑到这一点,您可以实现自己的绑定适配器,该适配器接受字符串资源的 ID 作为 int
参数。
@BindingAdapter("android:text")
fun setText(view: TextView, @StringRes resId: Int) {
if (resId == 0) {
view.text = null
} else {
view.setText(resId)
}
}
这将允许您使用标准的 android:text
属性通过其资源 ID 及其值来引用字符串。
<TextView
android:id="@+id/text_view_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{myPojo.resourceId}" />
答案 6 :(得分:0)
科特林版本:
@BindingAdapter("template", "resId")
fun TextView.setFormattedText(template: String, resId: Int) {
if (template.isEmpty() || resId == 0) return
text = template.format(resources.getString(resId))
}
在xml
中<TextView
app:template="@{@string/myFormatString}"
app:resId="@{viewModel.resourceId}"/>
答案 7 :(得分:0)
您可以在 XML 中使用上下文
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text= "@{context.getString(myPojo.resourceId)}"
/>