Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting a spannable string not working on a simple Textview

I cannot for the life of me understand why this simple code to set a spannable string is not working on this textview. The method below adds a "Today" marker, which should be in green, before the text displaying the date if the date is the current day.

private void setTimeTextView(String timeString) {

    Calendar c = Calendar.getInstance();

    String todaysDateString = ApiContentFormattingUtil.getFullDateFormat(c.getTime());
    if (timeString.equals(todaysDateString)){
        String todayText = getResources().getString(R.string.today_marker);

        Spannable timeSpannable = new SpannableString(todayText + timeString);
        timeSpannable.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.greenish_teal)), 0,
                todayText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        mDateTime.setText(timeSpannable);
    } else {
        mDateTime.setText(timeString);
    }
}

However, the color won't change.

enter image description here

Here is the XML for this view

<TextView
        android:id="@+id/newsfeed_date_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="23dp"
        android:textSize="12sp"
        android:textColor="@color/white_three"
        android:letterSpacing="0.06"
        app:fontPath="@string/opensans_bold_path"
        tools:text="Monday, January 1st"
        android:textAllCaps="true"
        tools:ignore="MissingPrefix"
        tools:targetApi="lollipop"/>
like image 768
TonyKazanjian Avatar asked Dec 06 '16 02:12

TonyKazanjian


People also ask

How to use Spannable in Android?

Use the Spannable. SPAN_EXCLUSIVE_INCLUSIVE flag to include inserted text, and use Spannable. SPAN_EXCLUSIVE_EXCLUSIVE to exclude the inserted text. val spannable = SpannableStringBuilder("Text is spantastic!")

What is span in Android Studio?

Spans can also be used to change TextPaint properties, draw on Canvas, and even change the text layout. In order to use spans, we have to use one of the classes listed below. Class. Mutable Text. Mutable Markup.

How do I limit the number of lines in a TextView?

gpetuhov/textview_limit_text. txt. This will limit number of lines to 1 and if text exceeds limit, TextView will display ... in the end of line.


1 Answers

On versions prior to Oreo, the android:textAllCaps="true" attribute setting will cause the formatting spans to be stripped from your text. You'll need to remove that setting (or set it to false), and handle the conversion to upper case yourself, before creating your SpannableString from it. For example:

String todayText = getResources().getString(R.string.today_marker);
String text = todayText + timeString;

Spannable timeSpannable = new SpannableString(text.toUpperCase());

This is due to a known bug in the platform AllCapsTransformationMethod class, which on versions Nougat 7.1 and below handles the text as a flat String, basically stripping any formatting spans you may have set.

Unfortunately, the support/androidx libraries also use the platform AllCapsTransformationMethod class, so this will happen for their textAllCaps attributes, as well; i.e., app:textAllCaps is broken pre-Oreo, too.

As indicated, this was corrected in Oreo, so this manual fix isn't strictly necessary on those newer versions. However, if you are still supporting pre-Oreo versions, it might be easier to just leave it off and handle the capitalization manually everywhere, rather than having to account for two different setups in your resources and code.

like image 198
Mike M. Avatar answered Oct 13 '22 04:10

Mike M.