Установка цвета текста с использованием привязки данных на Android

Я пытаюсь установить цвет текста TextView с помощью библиотеки привязки данных

android:textColor="@{holder.getTitleColor(context, item)}"

где метод в классе Holder определяется как ниже

public int getTitleColor(Context context, Item item) {
   ...
}

Независимо от того, возвращаю ли цвет int (@ColorInt) или ресурс цвета (@ColorRes), он окрашивает текст сплошным белым цветом. Что я делаю неправильно?

Ответ 1

Мне кажется, что int вы предоставляете, интерпретируется как шестнадцатеричный цвет, хотя кажется, что этот установщик должен ожидать идентификатор ресурса.

используйте ссылку на Context сгенерированную для каждого привязываемого представления, и используйте ее для преобразования идентификатора ресурса в цвет, на который вы указываете, как описано в Руководстве разработчика по привязке данных:

Специальная переменная с именем context генерируется для использования в выражениях привязки по мере необходимости. Значение для контекста - это контекст из корневого представления 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"/>
        ...
    </data>
    ...
     <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{data.text}"
            android:textColor="@{ContextCompat.getColor(context, data.colorRes)}"
            />
</layout>

Ответ 2

создать метод с помощью BindingAdapter

@BindingAdapter({"bind:color"})
public static void setFont(TextView textView, Item item) {
    textView.setTextColor(<set color of your choice>);
}

и вызвать его из xml

app:color="@{item}"

Ответ 3

Для установки части строки на цвет - это отлично работает с Kotlin, строковыми ресурсами и Databinding


  • Добавьте адаптер привязки (поместите это вне всех ваших классов)

    @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}" />
    

Результат:

enter image description here


Не используйте android:text="..." в вашем файле макета

Ответ 4

Создайте Binding Adapter следующим образом, здесь я передаю все строки, чтобы они были окрашены внутри {}. Замените {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>

Ответ 5

Чтобы установить цвет из целого числа, просто позвоните:

android:textColor="@{data.color}"

Ответ 6

В дополнение к решению @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, как показано выше.
  • Вы можете автоматически "контекст" в качестве параметра метода для ContextCompat.getColor(), потому что он будет автоматически разрешен в контексте представления.

Ответ 7

Вы также можете использовать привязку адаптера, а затем использовать цветовой ресурс.

Определите этот метод в любом месте проекта:

@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}"/>

Ответ 8

В моем случае значение цвета было в строковом формате (например, "# 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 all methods present
        tools:text="Test"/>
       ...... other views

4. Связывание с Activity/Adapter --in в моем случае это был Adapter

inner class ViewHolder(private val binding: BindingClass) :
    RecyclerView.ViewHolder(binding.root) {

    fun setData(data: DataClass, TxtColor : String?) {
        binding.txtColor= TxtColor 
        binding.executePendingBindings()
    }
}