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

问题描述 投票:26回答:8

我有一个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);

对于@Shailendra:search()方法将返回一些标题。我想强调那些与term词匹配的标题中的单词。我希望现在很清楚。

android android-listview highlighting textview
8个回答
38
投票

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

喜欢

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

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是文本着色的开始/停止索引,在这个例子中,“rti”将被着色。

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

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

然后用索引替换数字2和4,用标题字符串替换“部分彩色文本”。

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


3
投票

我知道这是一个古老的问题,但我已经创建了一种方法来突出显示string \ 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));

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


1
投票

试试这个库Android TextHighlighter

Implementations

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

1
投票

如果你的字符串是静态的,你可以在xml strings中这样做

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

1
投票

More Easy Way

您可以使用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获取可点击的突出显示文本。


0
投票

我知道这个线程很老,但是如果有人想要在textview中突出显示字符串,我已经创建了一个完全符合这个要求的库。这是我对堆栈溢出问题的第一个答案,因为我刚刚加入,希望它的格式正确且相关。它使用SpannableString并定位您指定的所有字符串。此外,还内置了一个自定义ClickableSpan,您可以根据需要为单击的文本设置侦听器。

Linker

轻量级的android库,用于突出显示textview内部的字符串(忽略大小写),带有可选的回调。

语言:Java

MinSDK:17

它的功能和所有代码的图像可以找到here

JavaDocs

要引入你的android项目实现工件:

在项目级别build.gradle中

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

在App level 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 - 调用链接器的更新方法以提交自定义并推出设置:

        linker.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 - 如果您希望为每个单词使用不同的设置,那么您还可以为链接器对象提供LinkProfiles的列表或数组:

        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许可证获得许可。

© www.soinside.com 2019 - 2024. All rights reserved.