我有一个自定义视图持有另一个。层次结构:
MyOuterView
->MyInnerView
MyInnerView
有一个枚举属性,如:
<attr name="myAttr" format="enum">
<enum name="foo" value="0"/>
<enum name="bar" value="1"/>
</attr>
所以我可以在MyOuterView
XML中实例化组件,如:
<com.example.MyInnerView
....
app:myAttr="foo"/>
当然有哪些作品。
MyOuterView
为自定义本身提供了一个参数。根据这个论点,我想设置MyInnerView
的参数。
希望的行为是我可以使用数据绑定,如:
<com.example.MyInnerView
....
app:myAttr="@{data.getMyAttr()}"/>
getMyAttr()
的样子:
public int getMyAttr() {
return myAttr; // returns 0 or 1
}
结果是编译问题。
**** /数据绑定错误**** msg:无法找到参数类型为int的属性'app:myAttr'的setter com.example.MyInnerView
所以显然我不能按值设置枚举,而只能按名称设置。除了以编程方式创建MyInnerView
之外还有什么想法?请注意,我无法更改MyInnerView
。
答案 0 :(得分:4)
我无法按值设置枚举,只能按名称设置
这不完全正确。即使按名称,您也无法使用DataBinding设置值,事实是xml中定义的属性的值通过构造函数传递给View
。 View
可以同时具有属性和设置器,但情况不一定如此。例如,您是否为android:text
的{{1}}设置了一个值,该值设置为TextView
,然后从构造函数中的com.android.internal.R.styleable.TextView_text
检索该值。如果您使用DataBinding,则会调用AttributeSet
,但这些是完全不同的2,功能相同,但它们在代码中没有关联。
鉴于您无法修改setText()
并且没有可以调用MyInnerView
的setter,您唯一的选择是通过构造函数传递它。 DataBinding根本不可行,即使使用BinderAdapter,您也无法在myAttr
中设置值,因为此时AttributeSet
已经实例化了。
选项1 - 主题
定义新属性
View
然后使用样式解析此属性,例如,您可以
<attr name="MyInnerViewAttrValue" format="integer" />
在布局xml
中设置它<style name="AppTheme.Foo">
<item name="MyInnerViewAttrValue">0</item>
</style>
<style name="AppTheme.Bar">
<item name="MyInnerViewAttrValue">1</item>
</style>
然后在实例化视图之前调用<com.example.MyInnerView
...
app:myAttr="?attr/MyInnerViewAttrValue" />
中的setTheme(int)
。
选项2 - 自定义BindingAdapter
如果你想设置你的值DataBinding(因为你有一个setter,或者你想用反射来破解Activity
),那么你需要创建一个自定义的BindingAdapter,例如
MyInnerView
然后在布局xml
@BindingAdapter("myAttrValue")
public static void setMyAttr(MyInnerView myInnerView, int value) {
switch (value) {
case 0:
myInnerView.foo();
break;
default:
myInnerView.bar();
}
}
并提供ViewModel的<com.example.lelloman.dummy.MyInnerView
...
myAttrValue="@{model.attr}" />
值
int
答案 1 :(得分:1)
不幸的是,只有当存在setter并且此setter映射到属性名称或者可以通过其名称解析时,才可以使用app:myAttr="@{...}"
之类的属性名称。
在您的情况下,如果此属性仅在View的构造函数中使用,并且视图没有任何公共方法可以更改此 - 您仍然有一些可能的解决方案:
- 扩展View和实现逻辑以自定义视图,如此属性do(如果可能)
- 制作BindingAdapter并使用Reflection(如果可能)。
- 通过复制粘贴和修复创建自己的视图)