设置一个 spannable 字符串不适用于简单的 Textview

Setting a spannable string not working on a simple Textview

我这辈子都无法理解为什么这个用于设置可跨越字符串的简单代码在这个文本视图上不起作用。如果日期是当前日期,下面的方法会在显示日期的文本之前添加一个 "Today" 标记,该标记应为绿色。

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);
    }
}

但是,颜色不会改变。

这是此视图的XML

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

在 Oreo 之前的版本中,android:textAllCaps="true" 属性设置会导致格式范围从您的文本中删除。在从中创建 SpannableString 之前,您需要删除该设置(或将其设置为 false),并自行处理大写转换。例如:

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

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

这是由于 a known bug in the platform AllCapsTransformationMethod class,它在 Nougat 7.1 及以下版本中将文本作为平面处理 String,基本上剥离了您可能已设置的任何格式跨度。

不幸的是,support/androidx 库也使用平台 AllCapsTransformationMethod class,因此它们的 textAllCaps 属性也会发生这种情况;也就是说,app:textAllCaps 在奥利奥之前也坏了。

如前所述,这已在 Oreo 中得到纠正,因此对于那些较新的版本而言,此手动修复并非绝对必要。但是,如果您仍然支持 Oreo 之前的版本,则可能更容易将其关闭并在任何地方手动处理大写,而不必在资源和代码中考虑两种不同的设置。