【问题标题】:highlight text inside a textview突出显示文本视图中的文本
【发布时间】:2016-11-25 08:27:25
【问题描述】:

我有一个带有随机背景颜色的 TextView(实际上可以是任何颜色)。我在这个 Textview 上也有一个需要可读的文本。 我认为最好的解决方案是以白色突出显示上述文本并将文本颜色设置为黑色。

我的问题是:是否可以从 XML 中突出显示 texview 中的文本?

我的布局中有以下内容:

  <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/colorButton4"
        android:layout_gravity="right|bottom"
        android:background="@drawable/layout_border"
        android:layout_marginRight="30dp"
        android:layout_marginBottom ="30dp"
        android:clickable="true"
        android:onClick="onClick"
        android:gravity="center"
        android:textColorHighlight="@color/bgWhite"
        android:textColor="@color/Black"
        android:text="5431354" />

但它不会突出显示文本。

【问题讨论】:

标签: android fonts textview highlight


【解决方案1】:

如果您检查过 TextView 的文档,您会发现 android:textColorHighlight 没有做您想做的事情:https://developer.android.com/reference/android/widget/TextView.html#attr_android:textColorHighlight

仅在选择文本时使用,例如在 EditText 中。您需要将 TextView 的背景设置为“突出显示”它。

【讨论】:

  • 我确实明白这一点。我的问题是可以通过其他方式吗?我假设没有,但作为菜鸟我会问,以防有我不知道的技巧。
  • 我不明白为什么当你想用黑色“突出显示”它时,你为什么要在文本视图中设置背景? ;)
  • 我想要一个带有随机背景颜色的 TextView 和“背景颜色为 ”的文字读,如果它回来了,我就读不下去了。我希望它能正确解释
【解决方案2】:

您可能希望为此使用SpannableString,它允许字符串的各个部分在 TextView 中以不同方式呈现。

像这样:

    SpannableString str = new SpannableString("Highlighted. Not highlighted.");
    str.setSpan(new BackgroundColorSpan(Color.YELLOW), 0, 11, 0);
    textView.setText(str);

【讨论】:

  • 所以你是在告诉我在我的 Java 代码中没有它是不可能的?
  • 可以通过使用一些特定的 HTML 标记来设置 strings.xml 中的文本样式。尝试以下答案之一:stackoverflow.com/questions/17559019/… 但使用背景颜色而不是字体颜色
  • 感谢您的链接。它给出了一些有趣的观点!遗憾的是,只有 XML 的解决方案都不起作用。我想我得为此使用一些 java 代码。
  • @Slamit 是的,我想,我还得写一些 java 代码来突出显示。
【解决方案3】:

要突出显示所有出现的特定文本,请使用以下方法:

private void highlightString(String input) {
//Get the text from text view and create a spannable string
SpannableString spannableString = new SpannableString(mTextView.getText());
//Get the previous spans and remove them
BackgroundColorSpan[] backgroundSpans = spannableString.getSpans(0, spannableString.length(), BackgroundColorSpan.class);

for (BackgroundColorSpan span: backgroundSpans) {
    spannableString.removeSpan(span);
}

//Search for all occurrences of the keyword in the string
int indexOfKeyword = spannableString.toString().indexOf(input);

while (indexOfKeyword > 0) {
    //Create a background color span on the keyword
    spannableString.setSpan(new BackgroundColorSpan(Color.YELLOW), indexOfKeyword, indexOfKeyword + input.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

    //Get the next index of the keyword
    indexOfKeyword = spannableString.toString().indexOf(input, indexOfKeyword + input.length());
}

//Set the final text on TextView
mTextView.setText(spannableString);}

注意:mTextView 是一个 TextView 对象,您要在其中突出显示文本

【讨论】:

  • while (indexOfKeyword != -1) { ... } 同时突出显示文本中的第一个单词。
  • 这个答案不会让你的应用变慢,就像上面列出的答案一样,当正在处理的数据大于 5,000 个字符时。仅供参考
【解决方案4】:

简单的方法

您可以使用Spannable 类来格式化文本。

textView.setText("Hello, I am Awesome, Most Awesome"); // set text first
setHighLightedText(textView, "a"); // highlight all `a` in TextView

输出将如下图所示。

方法如下。

 /**
     * use this method to highlight a text in TextView
     *
     * @param tv              TextView or Edittext or Button (or derived from TextView)
     * @param textToHighlight Text to highlight
     */
    public void setHighLightedText(TextView tv, String textToHighlight) {
        String tvt = tv.getText().toString();
        int ofe = tvt.indexOf(textToHighlight, 0);
        Spannable wordToSpan = new SpannableString(tv.getText());
        for (int ofs = 0; ofs < tvt.length() && ofe != -1; ofs = ofe + 1) {
            ofe = tvt.indexOf(textToHighlight, ofs);
            if (ofe == -1)
                break;
            else {
                // set color here
                wordToSpan.setSpan(new BackgroundColorSpan(0xFFFFFF00), ofe, ofe + textToHighlight.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                tv.setText(wordToSpan, TextView.BufferType.SPANNABLE);
            }
        }
    }

您可以check this answer 获取可点击的高亮文本。

【讨论】:

  • 感谢您提出这个 Khemraj,这个问题非常严格,因为我需要从 XML 中执行此操作(所以不是通过 Java)。可悲的是,您提供的东西无济于事!我认为这是不可能的,并重新设计了我的布局作为替代解决方案!
  • 你应该取一个比“ofe”更好的名字。此外,您不需要在循环内调用“setText”。将其设置在它之外就足够了。
  • 我也不确定你是否需要 TextView.BufferType.SPANNABLE 的参数。没有它对我有用。你为什么放它?也许不适用于旧的 Android 版本?
  • 如何使匹配不区分大小写?
  • 这个答案会导致应用在处理/显示超过 5000 个字符时挂起。
【解决方案5】:

我编写了一个 Kotlin 方法,该方法将突出显示 String 中所有出现的所有关键字,并返回 SpannableString

fun main() {
    textView.text = highlightKeywords(
        highlightColor = ContextCompat.getColor(context, R.color.colorAccent),
        message = "Hello World, and Hello to all my Hello Friends.",
        keywords = listOf("Hello")
    )
}


fun highlightKeywords(
    highlightColor: Int,
    message: String,
    keywords: List<String>,
): SpannableString {
    val spannableString = SpannableString(message)
    keywords.forEach { keyword ->
        if (!keyword.isBlank()) {
            var startIndex = message.indexOf(keyword)

            while (startIndex >= 0) {
                spannableString.setSpan(
                    ForegroundColorSpan(highlightColor),
                    startIndex,
                    startIndex + keyword.length,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                )

                startIndex = message.indexOf(keyword, startIndex + keyword.length)
            }
        }
    }
    return spannableString
}

【讨论】:

  • 这是一个非常古老的问题,它是关于使用仅 XML 的解决方案。谢谢你分享这个!
  • 好吧,如果您愿意,从技术上讲,您仍然可以使用 XML 中的 DataBinding 方法来触发 Kotlin 扩展方法。
【解决方案6】:

在 Android 上工作了 4 年后,我可以可以肯定地说,没有 XML 之外的代码是不可能的。 如果您可以使用一些代码,其他人分享的解决方案将对您有所帮助,请阅读!

编辑:我选择了一个有效的新答案,但它需要编写自定义 TextView!

【讨论】:

    【解决方案7】:

    Suraj's answer 很棒并且可以工作,但是缺少 2 个组件。首先,它不会突出显示第一个单词(如Rany 评论的那样),其次,它不会忽略大小写,因此在此字符串中搜索"test""This is a Test" 将找不到任何内容。

    这是我更新的答案,它通过传递的参数解决了这两个问题,并且还添加了 alpha,以防您想使用自定义颜色进行突出显示。请注意,重载的第一个方法是一个示例,说明如何返回前一个方法所做的操作,而不是选择第一个项目。

        
        /**
         * Use this method to get the same return as the previous method
         */
        public static SpannableString buildHighlightString(String originalText, String textToHighlight){
            return buildHighlightString(originalText, textToHighlight, false, Color.YELLOW, 1.0F);
        }
        
        /**
         * Build a spannable String for use in highlighting text colors
         * 
         * @param originalText The original text that is being highlighted
         * @param textToHighlight The text / query that determines what to highlight
         * @param ignoreCase Whether or not to ignore case. If true, will ignore and "test" will have
         *                   the same return as "TEST". If false, will return an item as highlighted
         *                   only if it matches it case specficic.
         * @param highlightColor The highlight color to use. IE {@link Color#YELLOW} || {@link Color#BLUE}
         * @param colorAlpha Alpha to adjust how transparent the color is. 1.0 means it looks exactly
         *                   as it should normally where as 0.0 means it is completely transparent and
         *                   see-through. 0.5 means it is 50% transparent. Useful for darker colors
         */
        public static SpannableString buildHighlightString(String originalText, String textToHighlight,
                                                           boolean ignoreCase, @ColorInt int highlightColor,
                                                           @FloatRange(from = 0.0, to = 1.0) float colorAlpha){
            SpannableString spannableString = new SpannableString(originalText);
            if (TextUtils.isEmpty(originalText) || TextUtils.isEmpty(textToHighlight)) {
                return spannableString;
            }
            String lowercaseOriginalString = originalText.toLowerCase();
            String lowercaseTextToHighlight = textToHighlight.toLowerCase();
            if(colorAlpha < 1){
                highlightColor = ColorUtils.setAlphaComponent(highlightColor, ((int)(255*colorAlpha)));
            }
            //Get the previous spans and remove them
            BackgroundColorSpan[] backgroundSpans = spannableString.getSpans(0, spannableString.length(), BackgroundColorSpan.class);
            for (BackgroundColorSpan span: backgroundSpans) {
                spannableString.removeSpan(span);
            }
            //Search for all occurrences of the keyword in the string
            int indexOfKeyword = (ignoreCase)
                    ? lowercaseOriginalString.indexOf(lowercaseTextToHighlight)
                    : originalText.indexOf(textToHighlight);
            while (indexOfKeyword != -1) {
                //Create a background color span on the keyword
                spannableString.setSpan(new BackgroundColorSpan(highlightColor), indexOfKeyword,
                        indexOfKeyword + (textToHighlight.length()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                
                //Get the next index of the keyword
                indexOfKeyword = (ignoreCase)
                        ? lowercaseOriginalString.indexOf(lowercaseTextToHighlight, (indexOfKeyword) + textToHighlight.length())
                        : originalText.indexOf(textToHighlight, (indexOfKeyword) + textToHighlight.length());
            }
            return spannableString;
        }
        
    

    【讨论】:

      【解决方案8】:

      https://github.com/datanapps/HighlightedTextView

      <datanapps.highlightedtextview.HighLightTextView
          android:id="@+id/tv2"
          android:layout_below="@+id/tv1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="Android is an open source and Linux-based operating system for mobile devices such as smartphones and tablet computers."
          android:textColor="@color/white"
          app:fontFamily="serif"
          android:lineSpacingExtra="50sp"
          android:layout_marginTop="20dp"
          android:textSize="20sp"
          android:textAlignment="viewEnd"
          app:highLightColor="@color/blue"
          />
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-30
        • 2015-05-09
        • 2012-11-08
        • 1970-01-01
        • 1970-01-01
        • 2011-08-31
        • 1970-01-01
        相关资源
        最近更新 更多