Установка цвета текста с использованием привязки данных на 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()
}
}