Android Spannable多个setSpan在一个TextView中

时间:2018-03-19 09:07:29

标签: android

我在我的应用程序中开发了一个简单的搜索框,我想在一个句子中突出显示多个单词。

我使用SpannableString在一个句子中添加多个范围。 这里函数写了

private CharSequence highlightText(String text, String query) {
    if (query != null && !query.isEmpty()) {

        Spannable spannable = new SpannableString(text);
        ForegroundColorSpan highlightSpan = new ForegroundColorSpan(Color.BLUE);

        String[] queryParts = query.split(" ");
        for (String queryPart : queryParts) {
            int startPos = text.toLowerCase(Locale.US).indexOf(queryPart.toLowerCase(Locale.US));
            int endPos = startPos + queryPart.length();

            if (startPos != -1) {
                Log.d(TAG, "find: '" + queryPart + "' in '" + text + "' (" + startPos + ")");
                spannable.setSpan(highlightSpan, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        return spannable;

    } else {
        return text;
    }
}

当我用

来调用此功能时
TextView spannableTest = findViewById(R.id.spannable_test);
spannableTest.setText(highlightText(
            "Lorem ipsum dolor sit amet, consectetur adipisicing elit.",
            "ipsum consect"));

我有这个日志

 D/SPAN: find: 'ipsum' in 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' (6)
 D/SPAN: find: 'consect' in 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' (28)

但在结果屏幕上,只有最后一次出现才会被突出显示

Result image

2 个答案:

答案 0 :(得分:3)

@pskink指出我应该ForegroundColorSpan highlightSpan = new ForegroundColorSpan(Color.BLUE);移动到for循环。

答案 1 :(得分:0)

将此文件添加到您的项目中: RichTextView.java

package com.outpace.expert.utility;

import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.URLSpan;
import android.view.View;

/**
 * Created by Deep Patel on 19-11-16
 */

//.setText(text, TextView.BufferType.SPANNABLE); to textView if not work
public class RichTextView extends SpannableString {
    private String syntax;

    public RichTextView(String syntax) {
        super(syntax);
        this.syntax = syntax;
    }

    public RichTextView setTextColor(String word, int color) {
        setSpan(new ForegroundColorSpan(color), syntax.indexOf(word), syntax.indexOf(word) + word.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    public RichTextView setSize(String word, float howMuch) {
        setSpan(new RelativeSizeSpan(howMuch), syntax.indexOf(word), syntax.indexOf(word) + word.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    public RichTextView setStrikeOut(String word) {
        setSpan(new StrikethroughSpan(), syntax.indexOf(word), syntax.indexOf(word) + word.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    public RichTextView setUrl(String word, String redirectUrl) {
        setSpan(new URLSpan(redirectUrl), syntax.indexOf(word), syntax.indexOf(word) + word.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    public RichTextView setBold(String word) {
        StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
        setSpan(boldSpan, syntax.indexOf(word), syntax.indexOf(word) + word.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    //setMovementMethod(LinkMovementMethod.getInstance()); after or before call
    public RichTextView setClickable(String word, final setOnLinkClickListener listener) {
        ClickableSpan clickableSpan = new ClickableSpan() {
            @Override
            public void onClick(View view) {
                if (listener != null) {
                    listener.onLinkClicked();
                }
            }
        };
        setSpan(clickableSpan, syntax.indexOf(word), syntax.indexOf(word) + word.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return this;
    }

    public interface setOnLinkClickListener {
        void onLinkClicked();
    }
}

以下是使用方法:

String data = model.getMessage().replace("{from_name}", model.getFromUser()); // String to display

tvNotificationText.setText(new RichTextView(data)
                    .setBold(model.getFromUser())    // bold 
                    .setTextColor(model.getFromUser(), ContextCompat.getColor(mContext, R.color.textPrimary))); // set text color for specific string

还有其他跨越选项,请探索并获得最佳解决方案!

快乐编码!!