繁体   English   中英

如何在Android布局中按值而不是名称设置枚举属性?

[英]How to set enum attribute by value instead of name in Android Layout?

我有一个自定义视图持有另一个。 层次:

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:在com.example.MyInnerView上找不到参数类型为int的属性'app:myAttr'的setter

所以显然我不能通过值设置枚举,而只能通过名称设置枚举。 除了以编程方式创建MyInnerView之外还有什么想法? 请注意,我无法更改MyInnerView

我不能按值设置枚举,只能按名称设置

这并非完全正确。 您甚至无法通过名称使用DataBinding设置值,事实是xml中定义的属性的值通过构造函数传递给View View可以同时具有属性和setter,但情况不一定如此。 例如,您是为TextView android:text设置了一个值,该值设置为com.android.internal.R.styleable.TextView_text ,然后从构造函数的AttributeSet中检索该值。 如果使用DataBinding,则会调用setText() ,但这些是两个完全不同的东西,功能相同,但它们在代码中没有关联。

鉴于您无法修改MyInnerView并且没有可以调用myAttr setter,您唯一的选择是通过构造函数传递它。 DataBinding是不可行的,即使使用BinderAdapter,您也无法在AttributeSet设置值,因为View已经在该点实例化了。

选项1 - 主题

定义新属性

<attr name="MyInnerViewAttrValue" format="integer" />

然后使用样式解析此属性,例如您可以使用

<style name="AppTheme.Foo">
    <item name="MyInnerViewAttrValue">0</item>
</style>

<style name="AppTheme.Bar">
    <item name="MyInnerViewAttrValue">1</item>
</style>

在布局xml中设置它

<com.example.MyInnerView
    ...
    app:myAttr="?attr/MyInnerViewAttrValue" />

然后在实例化视图之前在Activity调用setTheme(int)

选项2 - 自定义BindingAdapter

如果你想设置你的值DataBinding(因为你有一个setter,或者你想用反射破解MyInnerView ),那么你需要创建一个自定义的BindingAdapter,例如

@BindingAdapter("myAttrValue")
public static void setMyAttr(MyInnerView myInnerView, int value) {
    switch (value) {
        case 0:
            myInnerView.foo();
            break;
        default:
            myInnerView.bar();
    }
}

然后在布局xml中

<com.example.lelloman.dummy.MyInnerView
    ...
    myAttrValue="@{model.attr}" />

并从ViewModel中提供int

public class MyInnerViewModel {

    public int getAttr() {
        return 1234;
    }
}

不幸的是,你可以使用属性名称,例如app:myAttr="@{...}"只有当有setter并且这个setter被映射到属性名称或者可以通过其名称解析时。 在您的情况下,如果此属性仅在View的构造函数中使用,并且视图没有任何公共方法可以更改它 - 您仍然有一些可能的解决方案: - 扩展View并实现逻辑以自定义视图,如此属性do(如果可能) - make BindingAdapter并使用Reflection(如果可能)。 - 通过复制粘贴和修复​​创建自己的视图

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM