在 Android 上使用数据绑定设置文本颜色
Set text color using data binding on Android
我正在尝试使用数据绑定库TextView
设置文本颜色
android:textColor="@{holder.getTitleColor(context, item)}"
Holder
class中的方法定义如下
public int getTitleColor(Context context, Item item) {
...
}
无论我是 return color int (@ColorInt
) 还是 color resource (@ColorRes
),它都会将文本绘制为纯白色。我做错了什么?
使用 BindingAdapter
创建方法
@BindingAdapter({"bind:color"})
public static void setColor(TextView textView, Item item) {
textView.setTextColor(<set color of your choice>);
}
并从 xml
调用它
app:color="@{item}"
我似乎将您提供的 int
解释为十六进制颜色,尽管这 setter 应该期待资源 ID 似乎很直观。
使用为每个可绑定视图生成的 Context
引用,并使用它将资源 ID 转换为您指向的颜色,如 described in the DataBinding Dev Guide:
A special variable named context is generated for use in binding expressions as needed. The value for context is the Context from the root View's getContext().
使用它来设置颜色,如下所示:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{data.text}"
android:textColor="@{context.getColor(data.colorRes)}"
/>
编辑
为了向后兼容,您可以使用 ContextCompat。需要导入:
<layout>
<data>
<import type="android.support.v4.content.ContextCompat"/>
<variable name="data" type="com.whatever.myapp.MyModel"/>
...
</data>
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{data.text}"
android:textColor="@{ContextCompat.getColor(context, data.colorRes)}"
/>
</layout>
如下创建绑定适配器,这里我将所有要着色的字符串传递到{}
中。在 span.
中用彩色 blah
字符串替换 {blah}
字符串
@BindingAdapter( "spanColor")
fun formatText(view:TextView, hexColorValue:Int) {
val text = view.text
val span = SpannableStringBuilder(text)
var i = 0
var diff = 0
while (i < text.length) {
val firstIndex = text.indexOf('{', i) - diff
val secondIndex = text.indexOf('}', i) - diff
if (firstIndex < 0 || secondIndex < 0) break
span.delete(firstIndex, firstIndex + 1)
span.delete(secondIndex - 1, secondIndex)
span.setSpan(ForegroundColorSpan(hexColorValue), firstIndex, secondIndex-1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
i = secondIndex + diff + 1
diff += 2
}
view.text = span
}
在您的 XMl 文件中使用属性 (app:spanColor="@{@color/colorAccent}"
) 作为
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="@dimen/space_xlarge"
style="@style/DefaultSmallText"
app:spanColor="@{@color/colorAccent}"
android:text="@string/create_credential_message"/>
string.xml
<string name="create_credential_message"><![CDATA[{Username} must at least contain 8 alphanumeric characters or an email address. {Password} must be 8-20 characters long, contain uppercase, lowercase, number, & special characters.]]></string>
用于将部分字符串设置为颜色 - 这与 Kotlin、字符串资源和数据绑定完美结合
添加绑定适配器(将其放在所有 类 之外)
@BindingAdapter("app:full_text", "app:span_text", "app:span_color")
fun formatText(textView: TextView, full_text: String, span_text: String, span_color: Int) {
val firstMatchingIndex = full_text.indexOf(span_text)
val lastMatchingIndex = firstMatchingIndex + span_text.length
val spannable = SpannableString(full_text)
spannable.setSpan(ForegroundColorSpan(span_color), firstMatchingIndex, lastMatchingIndex, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
textView.text = spannable
}
设置带变量的字符串资源
<string name="percentage">%1$d\%%</string>
<string name="booking_fee">Require card and collect %1$s at Booking</string>
将值转换为 ViewHolder 中的字符串(如果需要)
fun bind(percentage: Int) {
binding.percentage = context.resources.getString(R.string.percentage, percentage)
binding.executePendingBindings()
}
通过您的 xml 布局应用绑定
<data>
<variable
name="percentage"
type="String" />
</data>
<TextView
...
app:full_text="@{@string/booking_fee(percentage)}"
app:span_color="@{@color/color_primary}"
app:span_text="@{percentage}" />
结果:
不要在布局文件中使用android:text="..."
要从整数设置颜色,只需调用:
android:textColor="@{data.color}"
除了@Mardann 的解决方案之外,这里还有一个更新的解决方案,它也适用于 API 低于 23 的情况,方法是使用 ContextCompat.getColor():
<layout>
<data>
<import type="androidx.core.content.ContextCompat" />
<variable
name="data"
type="com.example.myapp.MyDataObject" />
</data>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{data.text}"
android:textColor="@{ContextCompat.getColor(context, data.colorRes)}"/>
</layout>
- 确保如上所示导入 ContextCompat。
- 您可以自动 'context' 作为 ContextCompat.getColor() 的方法参数,因为它将自动解析为视图的上下文。
您也可以使用绑定适配器,然后使用颜色资源。
在项目的任意位置定义此方法:
@BindingAdapter(value = "text_color") //customise your name here
public static void setTextColor(TextView view, int color) {
view.setTextColor(color);
}
然后在 XML 中使用您的新属性:
<TextView
app:text_color="@{@color/colorPrimary}"/>
在我的例子中,颜色值是字符串格式(例如“#000000”)
1.String TxtColor = "#000000"
2.导入"android.graphics.Color"
<layout>
<data>
<import type="android.graphics.Color"/>
<variable name="txtColor" type="String"/>
</data>
.... other views
</layout>
3.设置为所需的视图 -- 在我的例子中是 TextView
........ other views
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textcolor= "@{Color.parseColor(txtColor)}" //when we import android.graphics.Color we can access it's all methods present
tools:text="Test"/>
...... other views
4.从 Activity/Adapter 绑定——在我的例子中是 Adapter
inner class ViewHolder(private val binding: BindingClass) :
RecyclerView.ViewHolder(binding.root) {
fun setData(data: DataClass, TxtColor : String?) {
binding.txtColor= TxtColor
binding.executePendingBindings()
}
}
我的解决方案是在 xml:
中使用这个 TextView 声明
<TextView
...
android:textColor="@{model.getResultColor(context, index)}"
...
/>
视图模型中的这个方法:
fun getResultColor(index: Int): Int {
getItem(index)?.let { item ->
...
return Color.GRAY
}
object CustumBinderAdapter {
@JvmStatic
@BindingAdapter("text_color")
fun setTextColor(view: TextView, color: Int) {
when(color){
R.color.soft_green->{
view.setTextColor(Color.parseColor("#5abc6e"))
}
R.color.deep_orange->{
view.setTextColor(Color.parseColor("#e62e30"))
}
}
}
}
在XML中这样使用:
app:text_color="@{yourViewModel.yourIntColorValue}"
为textview创建一个扩展函数。
@BindingAdapter("android:colorId")
fun TextView.setTextColorValue(@ColorRes colorId: Int) {
if (colorId == 0) return
setTextColor(ContextCompat.getColor(context, colorId))
}
像这样在xml中使用它
<TextView
android:id="@+id/deliveryStatus"
android:colorId="@{model.deliveryStatusColor}" />
代码:
binding.color = ContextCompat.getColor(requireContext(), R.color.text_regular)
布局:
<variable
name="color"
type="Integer" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@{color}"/>
我正在尝试使用数据绑定库TextView
设置文本颜色
android:textColor="@{holder.getTitleColor(context, item)}"
Holder
class中的方法定义如下
public int getTitleColor(Context context, Item item) {
...
}
无论我是 return color int (@ColorInt
) 还是 color resource (@ColorRes
),它都会将文本绘制为纯白色。我做错了什么?
使用 BindingAdapter
@BindingAdapter({"bind:color"})
public static void setColor(TextView textView, Item item) {
textView.setTextColor(<set color of your choice>);
}
并从 xml
调用它app:color="@{item}"
我似乎将您提供的 int
解释为十六进制颜色,尽管这 setter 应该期待资源 ID 似乎很直观。
使用为每个可绑定视图生成的 Context
引用,并使用它将资源 ID 转换为您指向的颜色,如 described in the DataBinding Dev Guide:
A special variable named context is generated for use in binding expressions as needed. The value for context is the Context from the root View's getContext().
使用它来设置颜色,如下所示:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{data.text}"
android:textColor="@{context.getColor(data.colorRes)}"
/>
编辑
为了向后兼容,您可以使用 ContextCompat。需要导入:
<layout>
<data>
<import type="android.support.v4.content.ContextCompat"/>
<variable name="data" type="com.whatever.myapp.MyModel"/>
...
</data>
...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{data.text}"
android:textColor="@{ContextCompat.getColor(context, data.colorRes)}"
/>
</layout>
如下创建绑定适配器,这里我将所有要着色的字符串传递到{}
中。在 span.
blah
字符串替换 {blah}
字符串
@BindingAdapter( "spanColor")
fun formatText(view:TextView, hexColorValue:Int) {
val text = view.text
val span = SpannableStringBuilder(text)
var i = 0
var diff = 0
while (i < text.length) {
val firstIndex = text.indexOf('{', i) - diff
val secondIndex = text.indexOf('}', i) - diff
if (firstIndex < 0 || secondIndex < 0) break
span.delete(firstIndex, firstIndex + 1)
span.delete(secondIndex - 1, secondIndex)
span.setSpan(ForegroundColorSpan(hexColorValue), firstIndex, secondIndex-1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
i = secondIndex + diff + 1
diff += 2
}
view.text = span
}
在您的 XMl 文件中使用属性 (app:spanColor="@{@color/colorAccent}"
) 作为
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="@dimen/space_xlarge"
style="@style/DefaultSmallText"
app:spanColor="@{@color/colorAccent}"
android:text="@string/create_credential_message"/>
string.xml
<string name="create_credential_message"><![CDATA[{Username} must at least contain 8 alphanumeric characters or an email address. {Password} must be 8-20 characters long, contain uppercase, lowercase, number, & special characters.]]></string>
用于将部分字符串设置为颜色 - 这与 Kotlin、字符串资源和数据绑定完美结合
添加绑定适配器(将其放在所有 类 之外)
@BindingAdapter("app:full_text", "app:span_text", "app:span_color") fun formatText(textView: TextView, full_text: String, span_text: String, span_color: Int) { val firstMatchingIndex = full_text.indexOf(span_text) val lastMatchingIndex = firstMatchingIndex + span_text.length val spannable = SpannableString(full_text) spannable.setSpan(ForegroundColorSpan(span_color), firstMatchingIndex, lastMatchingIndex, Spannable.SPAN_INCLUSIVE_EXCLUSIVE) textView.text = spannable }
设置带变量的字符串资源
<string name="percentage">%1$d\%%</string> <string name="booking_fee">Require card and collect %1$s at Booking</string>
将值转换为 ViewHolder 中的字符串(如果需要)
fun bind(percentage: Int) { binding.percentage = context.resources.getString(R.string.percentage, percentage) binding.executePendingBindings() }
通过您的 xml 布局应用绑定
<data> <variable name="percentage" type="String" /> </data> <TextView ... app:full_text="@{@string/booking_fee(percentage)}" app:span_color="@{@color/color_primary}" app:span_text="@{percentage}" />
结果:
不要在布局文件中使用android:text="..."
要从整数设置颜色,只需调用:
android:textColor="@{data.color}"
除了@Mardann 的解决方案之外,这里还有一个更新的解决方案,它也适用于 API 低于 23 的情况,方法是使用 ContextCompat.getColor():
<layout>
<data>
<import type="androidx.core.content.ContextCompat" />
<variable
name="data"
type="com.example.myapp.MyDataObject" />
</data>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{data.text}"
android:textColor="@{ContextCompat.getColor(context, data.colorRes)}"/>
</layout>
- 确保如上所示导入 ContextCompat。
- 您可以自动 'context' 作为 ContextCompat.getColor() 的方法参数,因为它将自动解析为视图的上下文。
您也可以使用绑定适配器,然后使用颜色资源。
在项目的任意位置定义此方法:
@BindingAdapter(value = "text_color") //customise your name here
public static void setTextColor(TextView view, int color) {
view.setTextColor(color);
}
然后在 XML 中使用您的新属性:
<TextView
app:text_color="@{@color/colorPrimary}"/>
在我的例子中,颜色值是字符串格式(例如“#000000”)
1.String TxtColor = "#000000"
2.导入"android.graphics.Color"
<layout>
<data>
<import type="android.graphics.Color"/>
<variable name="txtColor" type="String"/>
</data>
.... other views
</layout>
3.设置为所需的视图 -- 在我的例子中是 TextView
........ other views
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textcolor= "@{Color.parseColor(txtColor)}" //when we import android.graphics.Color we can access it's all methods present
tools:text="Test"/>
...... other views
4.从 Activity/Adapter 绑定——在我的例子中是 Adapter
inner class ViewHolder(private val binding: BindingClass) :
RecyclerView.ViewHolder(binding.root) {
fun setData(data: DataClass, TxtColor : String?) {
binding.txtColor= TxtColor
binding.executePendingBindings()
}
}
我的解决方案是在 xml:
中使用这个 TextView 声明<TextView
...
android:textColor="@{model.getResultColor(context, index)}"
...
/>
视图模型中的这个方法:
fun getResultColor(index: Int): Int {
getItem(index)?.let { item ->
...
return Color.GRAY
}
object CustumBinderAdapter {
@JvmStatic
@BindingAdapter("text_color")
fun setTextColor(view: TextView, color: Int) {
when(color){
R.color.soft_green->{
view.setTextColor(Color.parseColor("#5abc6e"))
}
R.color.deep_orange->{
view.setTextColor(Color.parseColor("#e62e30"))
}
}
}
}
在XML中这样使用:
app:text_color="@{yourViewModel.yourIntColorValue}"
为textview创建一个扩展函数。
@BindingAdapter("android:colorId")
fun TextView.setTextColorValue(@ColorRes colorId: Int) {
if (colorId == 0) return
setTextColor(ContextCompat.getColor(context, colorId))
}
像这样在xml中使用它
<TextView
android:id="@+id/deliveryStatus"
android:colorId="@{model.deliveryStatusColor}" />
代码:
binding.color = ContextCompat.getColor(requireContext(), R.color.text_regular)
布局:
<variable
name="color"
type="Integer" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@{color}"/>