搜索字体高亮控件

本文介绍了一种在Android中实现搜索关键词高亮显示的方法。通过自定义TextViewSnippet类,可以根据搜索字符串在文本中找到匹配部分并进行高亮,同时考虑了文本宽度限制,确保展示效果良好。代码详细展示了如何测量文本宽度、截取合适长度的文本片段,并使用SpannableString设置高亮颜色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

搜索字体高亮控件


public class TextViewSnippet extends TextView {
    private static final String TAG = TextViewSnippet.class.getSimpleName();
    private static String sEllipsis = "\u2026";
    private String mFullText;
    private String mSearchString;
    private Context mContext;
    private int mHighlightColor;

    public TextViewSnippet(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;

        mHighlightColor = context.getResources().getColor(R.color.color_C05);

    }

    public TextViewSnippet(Context context) {
        super(context);
        mContext = context;

        mHighlightColor = context.getResources().getColor(R.color.color_C05);

    }

    public TextViewSnippet(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;

        mHighlightColor = context.getResources().getColor(R.color.color_C05);

    }

    /**
     * We have to know our width before we can compute the snippet string.  Do that
     * here and then defer to super for whatever work is normally done.
     */
    @SuppressLint("DrawAllocation")
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        if (MmsApp.MMS_DEBUG) {
            Log.d(TAG, "onLayout --------------------------------");
        }

        if (mFullText == null) {
            if (MmsApp.MMS_DEBUG) {
                Log.d(TAG, "mSearchString == null");
            }

            return;
        }

        String fullTextLower = mFullText.toLowerCase();
        String searchStringLower = mSearchString.toLowerCase();

        int startPos = 0;
        int searchStringLength = searchStringLower.length();
        int bodyLength = fullTextLower.length();

        startPos = fullTextLower.indexOf(searchStringLower);

        TextPaint tp = getPaint();
        float searchStringWidth = tp.measureText(mSearchString);
        float textFieldWidth = getWidth();
        String snippetString = null;

        if (searchStringWidth > textFieldWidth) {
            if (-1 == startPos) {
                return;
            }

            snippetString = mFullText.substring(startPos, startPos + searchStringLength);
        } else {
            if (MmsApp.MMS_DEBUG) {
                Log.v(TAG, "searchStringWidth <= textFieldWidth");
            }

            float ellipsisWidth = tp.measureText(sEllipsis);
            textFieldWidth -= (1F * ellipsisWidth); // assume we'll need one on both ends

            int offset = -1;
            int start = -1;
            int end = -1;

            while (true) {
                offset += 1;

                int newstart = Math.max(0, startPos - offset);
                int newend = Math.min(bodyLength, startPos + searchStringLength + offset);

                if (newstart == start && newend == end) {
                    break;
                }

                start = newstart;
                end = newend;

                String candidate = mFullText.substring(start, end);
                snippetString = String.format("%s%s%s", start == 0 ? "" : sEllipsis, candidate,
                        end == bodyLength ? "" : sEllipsis);

                if (tp.measureText(candidate) > textFieldWidth) {
                    break;
                }
            }
        }

        String snippetStringLower = snippetString.toLowerCase();
        SpannableString spannable = new SpannableString(snippetString);
        int start = 0;
        while (true) {
            int index = snippetStringLower.indexOf(searchStringLower, start);

            if (index == -1) {
                break;
            }

            spannable.setSpan(new ForegroundColorSpan(mHighlightColor),
                    index, index + searchStringLength, 0);

            start = index + searchStringLength;
        }

        setText(spannable);

        if (MmsApp.MMS_DEBUG) {
            Log.d(TAG, "onlayout end");
        }

        super.onLayout(changed, left, top, right, bottom);
    }

    public void setText(String fullText, String searchText) {
        if ((fullText == null) || (searchText == null)) {
            return;
        }
        mFullText = fullText;
        mSearchString = searchText;
        requestLayout();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值