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
个构建错误。
如果我为String
参数类型使用CharSequence
或thingy
,它将生成,但是随后我通过了String
,并且注释范围从字符串资源。
那么,我该怎么办?
SpannedString
(即您从getText()
而不是getString()
获得的信息),或getText()
以获取我的SpannedString
答案 0 :(得分:4)
作为表达式,@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"/>
答案 1 :(得分:3)
这也许是一种不太邪恶的方式:
定义带注释的字符串。
<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>
参考布局中的TypedArray
:
<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);
}
尽管有些牵连,但这还是可行的。如果有多个字符串,则可以扩展数组。
答案 2 :(得分:0)
使用此绑定适配器:
@BindingAdapter("thingy")
fun handleThingy(textView: TextView, @StringRes thingy: Int) { /* stuff goes here */ }
,而不是使用app:thingy="@{@string/my_annotated_string}"
,而是将资源传递到绑定中:thingy="@string/my_annotated_string"
(没有app:
)。
答案 3 :(得分:0)
一个人可以使用<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>
用@Bindable
注释的吸气剂应该是索引访问权限:
android:text="@{thingy.getSpanAt(index)}"
SpannedString缺少绑定它所需的getter,也没有一个可以向框架类中添加注释。