Android - 突出显示TextView中的单词?

时间:2011-07-27 11:32:36

标签: android android-listview highlighting textview

我有database search query在数据库中搜索用户输入的字词并返回Cursor

在我的ListActivity中,我有一个ListView来保存项目(光标项目)。 ListView项目布局基本上是TextView。我的意思是,ListView将是TextView的列表。

我想要的是突出search term TextView中出现的cursor = myDbHelper.search(term); //term: a word entered by the user. cursor.moveToFirst(); String[] columns = {cursor.getColumnName(1)}; int[] columnsLayouts = {R.id.item_title}; //item_title: the TextView holding the one raw ca = new SimpleCursorAdapter(this.getBaseContext(), R.layout.items_layout, cursor,columns , columnsLayouts); lv = getListView(); lv.setAdapter(ca); 。我的意思是突出显示:不同的颜色或不同的背景颜色或任何东西使它与文本的其余部分不同。

这可能吗?以及如何?

更新

search()

对于@Shailendra:term方法将返回一些标题。我想突出显示那些与{{1}}字匹配的标题中的单词。我希望现在很清楚。

9 个答案:

答案 0 :(得分:38)

为单词周围的颜色插入HTML代码并将其设置为textView。

喜欢

String newString = oldString.replaceAll(textToHighlight, "<font color='red'>"+textToHighlight+"</font>");
textView.setText(Html.fromHtml(newString));

答案 1 :(得分:21)

TextView textView = (TextView)findViewById(R.id.mytextview01);

//use a loop to change text color
Spannable WordtoSpan = new SpannableString("partial colored text");        
WordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 2, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(WordtoSpan);

数字2和4是文本着色的开始/停止索引,在本例中是&#34; rti&#34;会有色。

所以你基本上只需在标题中找到搜索词的起始索引:

int startIndex = titleText.indexOf(term);
int stopIndex = startIndex + term.length();

然后用索引和&#34;部分彩色文本&#34;替换数字2和4;用你的标题字符串。

来源:https://stackoverflow.com/a/10279703/2160827

答案 2 :(得分:3)

我知道它的旧问题,但我创建了一种方法来突出显示字符串\ paragraph中的重复单词。

private Spannable highlight(int color, Spannable original, String word) {
    String normalized = Normalizer.normalize(original, Normalizer.Form.NFD)
            .replaceAll("\\p{InCombiningDiacriticalMarks}+", "");

    int start = normalized.indexOf(word);
    if (start < 0) {
        return original;
    } else {
        Spannable highlighted = new SpannableString(original);
        while (start >= 0) {
            int spanStart = Math.min(start, original.length());
            int spanEnd = Math.min(start+word.length(), original.length());

            highlighted.setSpan(new ForegroundColorSpan(color), spanStart,
                    spanEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            start = normalizedText.indexOf(word, spanEnd);
        }
        return highlighted;
    }
}

用法:

textView.setText(highlight(primaryColor, textAll, wordToHighlight));

答案 3 :(得分:2)

我还没有这样做,但这看起来很有希望:

http://developer.android.com/reference/android/text/SpannableString.html
http://developer.android.com/guide/topics/resources/string-resource.html
  

public final void setText(CharSequence text)

     

从以下版本开始:API Level 1设置TextView的字符串值。的TextView   不接受类似HTML的格式,您可以使用文本进行格式化   XML资源文件中的字符串。要设置字符串样式,请附加   android.text.style。*对象是一个SpannableString,或者看看   有关设置示例的可用资源类型文档   格式化文本在XML资源文件中。

     

http://developer.android.com/reference/android/widget/TextView.html

答案 4 :(得分:2)

根据先前的答案,我开发了以下功能,您可以复制/粘贴它

 private void highlightMask(TextView textView, String text, String mask) {
            boolean highlightenabled = true;
            boolean isHighlighted = false;

            if (highlightenabled) {
                if (!TextUtils.isEmpty(text) && !TextUtils.isEmpty(mask)) {
                    String textLC = text.toLowerCase();
                    mask = mask.toLowerCase();

                    if (textLC.contains(mask)) {
                        int ofe = textLC.indexOf(mask, 0);
                        Spannable wordToSpan = new SpannableString(text);
                        for (int ofs = 0; ofs < textLC.length() && ofe != -1; ofs = ofe + 1) {
                            ofe = textLC.indexOf(mask, ofs);
                            if (ofe == -1) {
                                break;
                            } else {
                                // set color here
                                wordToSpan.setSpan(new BackgroundColorSpan(0xFFFFFF00), ofe, ofe + mask.length(),
                                                   Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                                textView.setText(wordToSpan, TextView.BufferType.SPANNABLE);
                                isHighlighted = true;
                            }
                        }

                    }
                }
            }

            if (!isHighlighted) {
                textView.setText(text);
            }
        }

答案 5 :(得分:1)

试试这个图书馆Android TextHighlighter

实现

TextView.setText()获取的参数Spannable不仅仅是CharacterSequence。 SpannableString有一个允许应用样式的方法setSpan()

参见CharacterStyle https://developer.android.com/reference/android/text/style/CharacterStyle.html

的直接子类列表
  • 在“Hello,World”
  • 中为单词“Hello”提供背景颜色和前景色的示例
Spannable spannable = new SpannableString("Hello, World");
// setting red foreground color
ForegroundSpan fgSpan = new ForegroundColorSpan(Color.red);
// setting blue background color
BackgroundSpan bgSpan = new BackgroundColorSPan(Color.blue);

// setSpan requires start and end index
// in our case, it's 0 and 5
// You can directly set fgSpan or bgSpan, however,
// to reuse defined CharacterStyle, use CharacterStyle.wrap()
spannable.setSpan(CharacterStyle.wrap(fgSpan), 0, 5, 0);
spannable.setSpan(CharacterStyle.wrap(bgSpan), 0, 5, 0);

// apply spannableString on textview
textView.setText(spannable);

答案 6 :(得分:1)

如果您的字符串是静态的,则在xml strings中这样做

<string name="my_text">This text is <font color='red'>red here</font></string>

答案 7 :(得分:1)

更简便的方法

您可以使用Spannable类来突出显示/格式化文本的一部分。

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

Output

这是方法。

 /**
     * 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以获得可点击的突出显示文本。

答案 8 :(得分:0)

我知道此线程很旧,但是以防万一有人在文本视图中突出显示字符串的情况,我创建了一个库来执行此操作。这是我对栈溢出问题的第一个答案,正如我刚刚加入的那样,希望它的格式正确且相关。它使用SpannableString,并将查找您指定的所有出现的字符串。此外,内置了自定义的ClickableSpan,可让您选择是否需要为单击的文本设置侦听器。

链接器

轻巧的android库,用于在textview中突出显示字符串(忽略大小写),并带有可选的回调。

语言:Java

MinSDK:17

可以看到其功能和所有代码的图像 here

JavaDocs

要将工件带入您的android项目,

在项目级别build.gradle

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

在应用程序级别build.gradle

       dependencies {
            implementation 'com.github.Gaineyj0349:Linker:1.2'
    }

使用方法:

1-使用textview构造一个Linker对象:

        Linker linker = new Linker(textView);

2-添加一个数组或字符串列表以在textview的文本中突出显示:

        ArrayList<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        linker.addStrings(list);

AND / OR

        String[] words = new String[]{"One", "Two", "Three"};
        linker.addStrings(words);

3-添加回调:(这是可选的):

       linker.setListener(new LinkerListener() {
            @Override
            public void onLinkClick(String charSequenceClicked) {

                // charSequenceClicked is the word that was clicked

                Toast.makeText(MainActivity.this, charSequenceClicked, Toast.LENGTH_SHORT).show();
            }
        });

4-调用链接程序的update方法以进行自定义并推出设置。

        linker.update();

您始终可以选择将字符串添加到链接器对象,只需确保在刷新刷新范围之后调用update方法即可。

    linker.addStrings("yoda");
    linker.update();

如果您需要具有相同链接器对象的新对象,只需调用

       linker.clearLinksList()

您还可以自定义链接:

1-自定义所有链接颜色:

      linker.setAllLinkColors(Color.BLUE);

2-自定义链接强调:

      linker.setAllLinkUnderline(false);

3-如果您希望为特定字符串自定义颜色或下划线设置(请注意,该字符串必须已经添加到链接器中):

      linker.setLinkColorForCharSequence("world", Color.MAGENTA);
      linker.setUnderlineModeForCharSequence("world", true);

4-如果您希望每个单词使用不同的设置,则还可以为链接器对象提供LinkProfile的列表或数组:

        ArrayList<LinkProfile> profiles = new ArrayList<>();
        profiles.add(new LinkProfile("hello world",
                Color.GREEN, false));
        profiles.add(new LinkProfile("goodbye cruel world",
                Color.RED, false));
        profiles.add(new LinkProfile("Whoa awesome!",
                Color.CYAN, true));


        linker.addProfiles(profiles);

只需记住在对链接器对象进行任何添加之后就调用.update()。

请注意,库将处理一些细微之处,例如添加两个相同的单词或单词的相同部分。例如,如果“ helloworld”和“ hello”是添加到链接器中的两个单词,则当它们在相同字符范围内时,“ helloworld”将优先于“ hello”。链接器将首先根据较大的单词进行排序,并在链接它们时跟踪所有跨度-避免出现重复和跨度交叉的问题。

根据MIT许可获得许可。