将 BindingAdapter 与资源中的字符串数组结合使用
Using a BindingAdapter with a string-array from the resources
我有一个 几乎 的简单想法:我想为具有数据绑定 API 和 BindingAdapter 的微调器生成一个适配器。这是我要使用的XML:
<Spinner
android:id="@+id/country"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:value="@{address.country}"
app:data="@{@array/countries}"
app:keys="@{@array/iso_3166_2}"/>
这里的地址是一个简单的 class,它有一个名为 country
的字段,它是一个字符串,将包含一个 ISO-3166-2 字符串。为简单起见,值将是 "DE" 或 "US".
这是我的简化版 arrays.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="iso_3166_2">
<item>DE</item>
<item>US</item>
</string-array>
<string-array name="countries">
<item>@string/country_DE</item>
<item>@string/country_US</item>
</string-array>
</resources>
对于绑定,我写了这个 BindingAdapter:
@BindingAdapter({"value", "data", "keys"})
public static void generateAdapter(Spinner spinner,
String value,
@ArrayRes int data,
@ArrayRes int keys) {
}
当我尝试编译代码时出现此错误:
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:Identifiers must have user defined types from the XML file. countries is missing it
file:path/to/the/spinner-above.xml
loc:95:31 - 95:39
****\ data binding error ****
我的xml的第95行是这一行:app:value="@{address.country}"
你看到我哪里做错了吗?
顺便说一句,我不确定与数组资源相关的注释是否正确?我发现无法将其限制为字符串数组。
你可以通过参考stringArray
而不是array
来获取它。这是我使用 recyclerView 从资源中获取价值所做的工作,它运行良好,它也可能对您有所帮助。
在string.xml
<string-array name="myItems">
<item>Item 1</item>
<item>Item 2</item>
<item>Item 3</item>
<item>Item 4</item>
<item>Item 5</item>
<item>Item 6</item>
</string-array>
在layout.xml
app:entries="@{@stringArray/fi}"
您的情况可以是 app:data="@{@stringArray/countries}"
或 app:keys="@{@stringArray/iso_3166_2}"
。
并在绑定方法中
@BindingAdapter({"entries"})
public static void entries(RecyclerView recyclerView, String[] array) {
//get all values in array[] variable.
}
参考了解更多。
如果您想访问数据绑定布局文件中的其他资源类型,请参阅源代码
public String toJava() {
final String context = "getRoot().getContext()";
final String viewName = requiresView() ? LayoutBinderWriterKt.getFieldName(mTarget) :
"getRoot()";
final String resources = viewName + ".getResources()";
final String resourceName = mPackage + "R." + getResourceObject() + "." + mResourceId;
if ("anim".equals(mResourceType)) return "android.view.animation.AnimationUtils.loadAnimation(" + context + ", " + resourceName + ")";
if ("animator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadAnimator(" + context + ", " + resourceName + ")";
if ("bool".equals(mResourceType)) return resources + ".getBoolean(" + resourceName + ")";
if ("color".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorFromResource(" + viewName + ", " + resourceName + ")";
if ("colorStateList".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorStateListFromResource(" + viewName + ", " + resourceName + ")";
if ("dimen".equals(mResourceType)) return resources + ".getDimension(" + resourceName + ")";
if ("dimenOffset".equals(mResourceType)) return resources + ".getDimensionPixelOffset(" + resourceName + ")";
if ("dimenSize".equals(mResourceType)) return resources + ".getDimensionPixelSize(" + resourceName + ")";
if ("drawable".equals(mResourceType)) return "android.databinding.DynamicUtil.getDrawableFromResource(" + viewName + ", " + resourceName + ")";
if ("fraction".equals(mResourceType)) {
String base = getChildCode(0, "1");
String pbase = getChildCode(1, "1");
return resources + ".getFraction(" + resourceName + ", " + base + ", " + pbase +
")";
}
if ("id".equals(mResourceType)) return resourceName;
if ("intArray".equals(mResourceType)) return resources + ".getIntArray(" + resourceName + ")";
if ("integer".equals(mResourceType)) return resources + ".getInteger(" + resourceName + ")";
if ("interpolator".equals(mResourceType)) return "android.view.animation.AnimationUtils.loadInterpolator(" + context + ", " + resourceName + ")";
if ("layout".equals(mResourceType)) return resourceName;
if ("plurals".equals(mResourceType)) {
if (getChildren().isEmpty()) {
return resourceName;
} else {
return makeParameterCall(resources, resourceName, "getQuantityString");
}
}
if ("stateListAnimator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadStateListAnimator(" + context + ", " + resourceName + ")";
if ("string".equals(mResourceType)) return makeParameterCall(resources, resourceName, "getString");
if ("stringArray".equals(mResourceType)) return resources + ".getStringArray(" + resourceName + ")";
if ("transition".equals(mResourceType)) return "android.transition.TransitionInflater.from(" + context + ").inflateTransition(" + resourceName + ")";
if ("typedArray".equals(mResourceType)) return resources + ".obtainTypedArray(" + resourceName + ")";
final String property = Character.toUpperCase(mResourceType.charAt(0)) +
mResourceType.substring(1);
return resources + ".get" + property + "(" + resourceName + ")";
}
我有一个 几乎 的简单想法:我想为具有数据绑定 API 和 BindingAdapter 的微调器生成一个适配器。这是我要使用的XML:
<Spinner
android:id="@+id/country"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:value="@{address.country}"
app:data="@{@array/countries}"
app:keys="@{@array/iso_3166_2}"/>
这里的地址是一个简单的 class,它有一个名为 country
的字段,它是一个字符串,将包含一个 ISO-3166-2 字符串。为简单起见,值将是 "DE" 或 "US".
这是我的简化版 arrays.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="iso_3166_2">
<item>DE</item>
<item>US</item>
</string-array>
<string-array name="countries">
<item>@string/country_DE</item>
<item>@string/country_US</item>
</string-array>
</resources>
对于绑定,我写了这个 BindingAdapter:
@BindingAdapter({"value", "data", "keys"})
public static void generateAdapter(Spinner spinner,
String value,
@ArrayRes int data,
@ArrayRes int keys) {
}
当我尝试编译代码时出现此错误:
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
java.lang.RuntimeException: Found data binding errors.
****/ data binding error ****msg:Identifiers must have user defined types from the XML file. countries is missing it
file:path/to/the/spinner-above.xml
loc:95:31 - 95:39
****\ data binding error ****
我的xml的第95行是这一行:app:value="@{address.country}"
你看到我哪里做错了吗?
顺便说一句,我不确定与数组资源相关的注释是否正确?我发现无法将其限制为字符串数组。
你可以通过参考stringArray
而不是array
来获取它。这是我使用 recyclerView 从资源中获取价值所做的工作,它运行良好,它也可能对您有所帮助。
在string.xml
<string-array name="myItems">
<item>Item 1</item>
<item>Item 2</item>
<item>Item 3</item>
<item>Item 4</item>
<item>Item 5</item>
<item>Item 6</item>
</string-array>
在layout.xml
app:entries="@{@stringArray/fi}"
您的情况可以是 app:data="@{@stringArray/countries}"
或 app:keys="@{@stringArray/iso_3166_2}"
。
并在绑定方法中
@BindingAdapter({"entries"})
public static void entries(RecyclerView recyclerView, String[] array) {
//get all values in array[] variable.
}
参考
如果您想访问数据绑定布局文件中的其他资源类型,请参阅源代码
public String toJava() {
final String context = "getRoot().getContext()";
final String viewName = requiresView() ? LayoutBinderWriterKt.getFieldName(mTarget) :
"getRoot()";
final String resources = viewName + ".getResources()";
final String resourceName = mPackage + "R." + getResourceObject() + "." + mResourceId;
if ("anim".equals(mResourceType)) return "android.view.animation.AnimationUtils.loadAnimation(" + context + ", " + resourceName + ")";
if ("animator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadAnimator(" + context + ", " + resourceName + ")";
if ("bool".equals(mResourceType)) return resources + ".getBoolean(" + resourceName + ")";
if ("color".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorFromResource(" + viewName + ", " + resourceName + ")";
if ("colorStateList".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorStateListFromResource(" + viewName + ", " + resourceName + ")";
if ("dimen".equals(mResourceType)) return resources + ".getDimension(" + resourceName + ")";
if ("dimenOffset".equals(mResourceType)) return resources + ".getDimensionPixelOffset(" + resourceName + ")";
if ("dimenSize".equals(mResourceType)) return resources + ".getDimensionPixelSize(" + resourceName + ")";
if ("drawable".equals(mResourceType)) return "android.databinding.DynamicUtil.getDrawableFromResource(" + viewName + ", " + resourceName + ")";
if ("fraction".equals(mResourceType)) {
String base = getChildCode(0, "1");
String pbase = getChildCode(1, "1");
return resources + ".getFraction(" + resourceName + ", " + base + ", " + pbase +
")";
}
if ("id".equals(mResourceType)) return resourceName;
if ("intArray".equals(mResourceType)) return resources + ".getIntArray(" + resourceName + ")";
if ("integer".equals(mResourceType)) return resources + ".getInteger(" + resourceName + ")";
if ("interpolator".equals(mResourceType)) return "android.view.animation.AnimationUtils.loadInterpolator(" + context + ", " + resourceName + ")";
if ("layout".equals(mResourceType)) return resourceName;
if ("plurals".equals(mResourceType)) {
if (getChildren().isEmpty()) {
return resourceName;
} else {
return makeParameterCall(resources, resourceName, "getQuantityString");
}
}
if ("stateListAnimator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadStateListAnimator(" + context + ", " + resourceName + ")";
if ("string".equals(mResourceType)) return makeParameterCall(resources, resourceName, "getString");
if ("stringArray".equals(mResourceType)) return resources + ".getStringArray(" + resourceName + ")";
if ("transition".equals(mResourceType)) return "android.transition.TransitionInflater.from(" + context + ").inflateTransition(" + resourceName + ")";
if ("typedArray".equals(mResourceType)) return resources + ".obtainTypedArray(" + resourceName + ")";
final String property = Character.toUpperCase(mResourceType.charAt(0)) +
mResourceType.substring(1);
return resources + ".get" + property + "(" + resourceName + ")";
}