代码之家  ›  专栏  ›  技术社区  ›  CommonsWare

如何使用数据绑定从字符串资源中获取跨距对象?

  •  11
  • CommonsWare  · 技术社区  · 6 年前

    Florina Muntenescu写的 a cool post 关于使用 <annotation> 在字符串资源中,您可以使用自定义范围在应用程序中处理灵活的标记。我正试图在数据绑定中利用它,但我不太清楚如何获得 SpannedString 数据绑定中字符串资源的版本。

    在我的布局中,我有 app:thingy="@{@string/my_annotated_string}" 作为属性 TextView . 我有一个绑定适配器要处理 thingy 属性。然而,数据绑定系统似乎坚持认为我的价值是 String .

    我尝试过:

    @BindingAdapter("thingy")
    @JvmStatic
    fun handleThingy(textView: TextView, thingy: SpannedString) { /* stuff goes here */ }
    

    还有:

    @BindingAdapter("thingy")
    @JvmStatic
    fun handleThingy(textView: TextView, thingy: Spanned) { /* stuff goes here */ }
    

    还有:

    @BindingAdapter("thingy")
    @JvmStatic
    fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
    

    在任何情况下,我都会 Cannot find the setter for attribute 'app:thingy' with parameter type java.lang.String on android.widget.TextView 生成错误。

    如果我使用 CharSequence 对于 廷吉 参数类型,它生成,但随后我通过 而且我没有字符串资源的注释跨度。

    那么,我怎样才能:

    • 获取 活动扳手 对应于我的字符串资源(即,你从中得到的 getText() 而不是 getString() )
    • 获取字符串资源的字符串资源ID,以便调用 获取文本() 我自己去拿我的 活动扳手
    4 回复  |  直到 6 年前
        1
  •  4
  •   tynn    6 年前

    作为一种表达, @string/my_annotated_string 计算为字符串。尽管它类似于XML中的字符串资源引用,但实际上它只是 String 价值。

    如果有一个 @text/my_annotated_string 版本也一样,但从文档来看,这是不可用的。

    相反,您必须使用绑定表达式中的实际资源:

    app:thingy="@{string.my_annotated_string}"
    app:thingy="@{context.getText(string.my_annotated_string)}"
    

    这是假设 string 班级:

    <import type="path.to.R.string"/>
    
        2
  •  3
  •   Cheticamp    6 年前

    下面是一个稍微不那么恶心的方法:

    定义带批注的字符串。

    <string name="my_annotated_string">A <annotation font="title_emphasis">cool</annotation> annotation <annotation font="title_emphasis">thingy</annotation>.</string>
    

    将对该字符串资源的引用放入 TypedArray :

    <resources>
        <array name="annotated_text">
            <item>@string/my_annotated_string</item>
        </array>
    </resources>
    

    参考 Darray型 在布局中:

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:thingy="@{@typedArray/annotated_text}" />
    

    最后,设置 BindingAdapter 捕捉 SpannedString 带注释:

    @BindingAdapter("thingy")
    public static void setThingy(TextView textView, TypedArray strings) {
        SpannedString ss = (SpannedString) strings.getText(0);
        Object spans[] = ss.getSpans(0, ss.length(), Object.class);
    }
    

    虽然有点牵扯进来,但这是可行的。如果有多个字符串,则可以展开数组。

        3
  •  0
  •   Matt Twig    6 年前

    使用此绑定适配器:

    @BindingAdapter("thingy")
    fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
    

    而不是使用 app:thingy="@{@string/my_annotated_string}" 将资源传递到绑定: thingy="@string/my_annotated_string" (没有 app: )

        4
  •  0
  •   Martin Zeitler    6 年前

    可以定义任何数据类型 <import> :

    <data>
        <import type="android.util.SparseArray"/>
        <import type="java.util.Map"/>
        <import type="java.util.List"/>
        <variable name="list" type="List<String>"/>
        <variable name="sparse" type="SparseArray<String>"/>
        <variable name="map" type="Map<String, String>"/>
        <variable name="index" type="int"/>
        <variable name="key" type="String"/>
    </data>
    

    然后从中获取文本:

    android:text="@{sparse[index]}"
    

    定义 thingy 具有数据类型 SpannedString (或 extends SpannedString ):

    <data>
        <import type="com.acme.model.BindableSpannedString"/>
        <variable name="thingy" type="BindableSpannedString"/>
        <variable name="index" type="int"/>
    </data>
    

    getter用注释 @Bindable 应该是索引访问:

    android:text="@{thingy.getSpanAt(index)}"
    

    SpannedString 缺少绑定它所需的getter,也不能向框架类添加注释。