Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm trying to set
TextView
text color using data binding library
android:textColor="@{holder.getTitleColor(context, item)}"
where the method in Holder class is defined like below
public int getTitleColor(Context context, Item item) {
No matter if I return color int (@ColorInt) or color resource (@ColorRes) it paints the text solid white. What am I doing wrong?
I seems the int you are providing is interpreted as a hex color, even though it seem intuitive that this setter should be expecting a resource ID.
use the Context reference generated for each bindable view, and use it to convert the resource ID to the color you are pointing to, as 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().
use it to set color like this:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{data.text}"
android:textColor="@{context.getColor(data.colorRes)}"
for backwards compatibility you can use ContextCompat. Import needed:
<layout>
<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>
–
–
–
In addition to the solution of @Mardann, here is an updated solution that also works on API lower than 23 by using ContextCompat.getColor():
<layout>
<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>
Make sure to import ContextCompat as shown above.
You can automagically 'context' as method parameter for ContextCompat.getColor() because it will be automatically resolved to the view's context.
create method by using BindingAdapter
@BindingAdapter({"bind:color"})
public static void setColor(TextView textView, Item item) {
textView.setTextColor(<set color of your choice>);
and to call it from xml
app:color="@{item}"
–
–
In my case, the color value was in a String Format(eg. "#000000")
1.String TxtColor = "#000000"
2.Import "android.graphics.Color"
<layout>
<import type="android.graphics.Color"/>
<variable name="txtColor" type="String"/>
</data>
.... other views
</layout>
3.Set to Desired View -- In my case it was 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.Binding from Activity/Adapter --in my case it was Adapter
inner class ViewHolder(private val binding: BindingClass) :
RecyclerView.ViewHolder(binding.root) {
fun setData(data: DataClass, TxtColor : String?) {
binding.txtColor= TxtColor
binding.executePendingBindings()
Add your binding adapter (place this outside all your classes)
@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
Setup string resources with variables
<string name="percentage">%1$d\%%</string>
<string name="booking_fee">Require card and collect %1$s at Booking</string>
Convert value to string in your ViewHolder (if you need to)
fun bind(percentage: Int) {
binding.percentage = context.resources.getString(R.string.percentage, percentage)
binding.executePendingBindings()
Apply bindings via your xml layout
<variable
name="percentage"
type="String" />
</data>
<TextView
app:full_text="@{@string/booking_fee(percentage)}"
app:span_color="@{@color/color_primary}"
app:span_text="@{percentage}" />
Create an extension function for textview.
@BindingAdapter("android:colorId")
fun TextView.setTextColorValue(@ColorRes colorId: Int) {
if (colorId == 0) return
setTextColor(ContextCompat.getColor(context, colorId))
use it in xml like this
<TextView
android:id="@+id/deliveryStatus"
android:colorId="@{model.deliveryStatusColor}" />
You can also use binding adapter and then use color resource.
Define this method anywhere in project:
@BindingAdapter(value = "text_color") //customise your name here
public static void setTextColor(TextView view, int color) {
view.setTextColor(color);
And then in XML use your new attribute:
<TextView
app:text_color="@{@color/colorPrimary}"/>
Create Binding Adapter as follows, here I am passing all the strings to be colored inside {}. Replace the {blah} string with colored blah string in span.
@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
In your XMl file use the attribute (app:spanColor="@{@color/colorAccent}") as
<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>
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.