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

Mic*_*ger 18 java enums android android-layout android-databinding

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

MyOuterView
->MyInnerView
Run Code Online (Sandbox Code Playgroud)

MyInnerView 有一个枚举属性,如:

<attr name="myAttr" format="enum">
    <enum name="foo" value="0"/>
    <enum name="bar" value="1"/>
</attr>
Run Code Online (Sandbox Code Playgroud)

所以我可以在MyOuterViewXML中实例化组件,如:

<com.example.MyInnerView
....
app:myAttr="foo"/>
Run Code Online (Sandbox Code Playgroud)

当然哪个有效.这MyOuterView为定制本身提供了一个论据.根据这个论点,我想设置一个参数MyInnerView.

希望的行为是我可以使用数据绑定,如:

<com.example.MyInnerView
....
app:myAttr="@{data.getMyAttr()}"/>
Run Code Online (Sandbox Code Playgroud)

其中getMyAttr()的样子:

public int getMyAttr() {
    return myAttr; // returns 0 or 1
}
Run Code Online (Sandbox Code Playgroud)

结果是编译问题.

****/数据绑定错误****消息:在com.example.MyInnerView上找不到参数类型为int的属性'app:myAttr'的setter

所以显然我不能通过值设置枚举,而只能通过名称设置枚举.除了以MyInnerView编程方式创建之外的任何想法 请注意,我无法改变MyInnerView.

lel*_*man 5

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

这并不完全正确。即使按名称,您也无法使用 DataBinding 设置值,问题是在 xml 中定义的属性值View通过构造函数传递给。AView可以同时具有属性和设置器,但情况并非一定如此。例如,您是否为android:texta设置了一个值TextView,然后将该值设置为com.android.internal.R.styleable.TextView_textAttributeSet构造函数中的检索。如果使用 DataBinding,setText()则调用,但这是 2 个完全不同的东西,功能相同但它们在代码中不相关。

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

选项 1 - 主题

定义新属性

<attr name="MyInnerViewAttrValue" format="integer" />
Run Code Online (Sandbox Code Playgroud)

然后用一个样式解析这个属性,例如你可以有

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

<style name="AppTheme.Bar">
    <item name="MyInnerViewAttrValue">1</item>
</style>
Run Code Online (Sandbox Code Playgroud)

在布局xml中设置

<com.example.MyInnerView
    ...
    app:myAttr="?attr/MyInnerViewAttrValue" />
Run Code Online (Sandbox Code Playgroud)

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

选项 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在布局xml

<com.example.lelloman.dummy.MyInnerView
    ...
    myAttrValue="@{model.attr}" />
Run Code Online (Sandbox Code Playgroud)

int从您的 ViewModel 中给出价值

public class MyInnerViewModel {

    public int getAttr() {
        return 1234;
    }
}
Run Code Online (Sandbox Code Playgroud)