You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android搜索视图定制:展示含指定关键词段落并高亮关键词

Android 关键词搜索+段落高亮完整实现方案

嘿,刚好做过类似的需求,给你梳理一套落地的技术方案,分四步走就能搞定:

1. 先把XML里的段落读出来

假设你的段落XML放在res/raw/paragraphs.xml,结构大概是这样:

<paragraphs>
    <p>Your first paragraph content, maybe contains theft...</p>
    <p>Second paragraph without the keyword...</p>
    <p>Third paragraph with theft again...</p>
</paragraphs>

咱用XmlPullParser来解析,代码简单还高效:

private fun loadParagraphsFromXml(): List<String> {
    val paragraphs = mutableListOf<String>()
    val parser = resources.getXml(R.raw.paragraphs)
    var eventType = parser.eventType
    var currentParagraph = ""
    
    while (eventType != XmlPullParser.END_DOCUMENT) {
        when (eventType) {
            XmlPullParser.START_TAG -> {
                if (parser.name == "p") {
                    currentParagraph = ""
                }
            }
            XmlPullParser.TEXT -> {
                currentParagraph += parser.text
            }
            XmlPullParser.END_TAG -> {
                if (parser.name == "p" && currentParagraph.isNotEmpty()) {
                    paragraphs.add(currentParagraph.trim())
                }
            }
        }
        eventType = parser.next()
    }
    return paragraphs
}

2. 筛选出包含关键词的段落

遍历所有段落,判断是否包含目标关键词,记得做大小写不敏感处理(用户搜"Theft"也能匹配到):

fun filterParagraphs(keyword: String, allParagraphs: List<String>): List<String> {
    val lowerKeyword = keyword.lowercase()
    return allParagraphs.filter { paragraph ->
        paragraph.lowercase().contains(lowerKeyword)
    }
}

3. 高亮段落里的关键词

用SpannableString来实现高亮,写个工具方法批量处理:

fun highlightKeyword(paragraph: String, keyword: String): SpannableString {
    val spannable = SpannableString(paragraph)
    val lowerParagraph = paragraph.lowercase()
    val lowerKeyword = keyword.lowercase()
    var startIndex = lowerParagraph.indexOf(lowerKeyword)
    
    while (startIndex != -1) {
        val endIndex = startIndex + keyword.length
        // 设置背景高亮,你也可以改成文字颜色
        spannable.setSpan(
            BackgroundColorSpan(Color.YELLOW),
            startIndex,
            endIndex,
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        startIndex = lowerParagraph.indexOf(lowerKeyword, endIndex)
    }
    return spannable
}

4. 展示处理后的结果

用RecyclerView来展示最方便,Adapter里绑定数据的时候直接用高亮后的SpannableString:

class ParagraphAdapter(private val highlightedParagraphs: List<SpannableString>) :
    RecyclerView.Adapter<ParagraphAdapter.ViewHolder>() {

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvParagraph: TextView = itemView.findViewById(R.id.tv_paragraph)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_paragraph, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.tvParagraph.text = highlightedParagraphs[position]
    }

    override fun getItemCount() = highlightedParagraphs.size
}

最后整合调用的逻辑

// 初始化加载所有段落
val allParagraphs = loadParagraphsFromXml()

// 搜索时的逻辑
fun onSearchKeyword(keyword: String) {
    if (keyword.isEmpty()) {
        // 关键词为空时可以展示所有段落,或者提示用户输入
        return
    }
    // 筛选段落
    val filtered = filterParagraphs(keyword, allParagraphs)
    // 批量高亮
    val highlighted = filtered.map { highlightKeyword(it, keyword) }
    // 更新RecyclerView
    val adapter = ParagraphAdapter(highlighted)
    recyclerView.adapter = adapter
}

这样就能实现你要的效果:搜单个关键词,只显示包含它的段落,还自动高亮关键词。如果需要调整高亮样式,直接改BackgroundColorSpan成其他Span就行~

内容的提问来源于stack exchange,提问作者lakshman kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 07:03:23