全文搜索界面优化 #262

This commit is contained in:
HapeLee
2025-11-09 16:17:32 +08:00
parent 55bf83e845
commit 8add267239
4 changed files with 94 additions and 58 deletions
@@ -61,13 +61,7 @@ class SearchContentActivity :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// val bbg = bottomBackground
// val btc = getPrimaryTextColor(ColorUtils.isColorLight(bbg))
// binding.llSearchBaseInfo.setBackgroundColor(bbg)
binding.llSearchBaseInfo.applyNavigationBarPadding()
// binding.tvCurrentSearchInfo.setTextColor(btc)
// binding.ivSearchContentTop.setColorFilter(btc)
// binding.ivSearchContentBottom.setColorFilter(btc)
val searchResultList = IntentData.get<List<SearchResult>>("searchResultList")
val position = intent.getIntExtra("searchResultIndex", 0)
val noSearchResult = searchResultList == null
@@ -143,7 +137,6 @@ class SearchContentActivity :
private fun initRecyclerView() {
binding.recyclerView.layoutManager = mLayoutManager
binding.recyclerView.addItemDecoration(VerticalDivider(this))
binding.recyclerView.adapter = adapter
}
@@ -1,21 +1,19 @@
package io.legado.app.ui.book.searchContent
//import io.legado.app.lib.theme.accentColor
import android.content.Context
import android.view.ViewGroup
import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.RecyclerAdapter
import io.legado.app.databinding.ItemSearchListBinding
import io.legado.app.utils.hexString
import io.legado.app.utils.themeColor
class SearchContentAdapter(context: Context, val callback: Callback) :
RecyclerAdapter<SearchResult, ItemSearchListBinding>(context) {
val textColor = context.themeColor(com.google.android.material.R.attr.colorOnSurface).hexString.substring(2)
val accentColor =
context.themeColor(androidx.appcompat.R.attr.colorPrimary).hexString.substring(2)
private val textColorInt = context.themeColor(com.google.android.material.R.attr.colorOnSurface)
private val accentColorInt = context.themeColor(androidx.appcompat.R.attr.colorPrimary)
private val bgColorInt = context.themeColor(com.google.android.material.R.attr.colorSecondaryContainer)
override fun getViewBinding(parent: ViewGroup): ItemSearchListBinding {
return ItemSearchListBinding.inflate(inflater, parent, false)
@@ -30,14 +28,19 @@ class SearchContentAdapter(context: Context, val callback: Callback) :
binding.run {
val isDur = callback.durChapterIndex() == item.chapterIndex
if (payloads.isEmpty()) {
tvSearchResult.text = item.getHtmlCompat(textColor, accentColor)
tvSearchResult.paint.isFakeBoldText = isDur
tvTitle.text = item.getTitleSpannable(textColorInt)
tvContent.text = item.getContentSpannable(textColorInt, accentColorInt, bgColorInt)
cdRoot.setCardBackgroundColor(
if (isDur) context.themeColor(com.google.android.material.R.attr.colorSurfaceContainer)
else context.themeColor(com.google.android.material.R.attr.colorSurface)
)
}
}
}
override fun registerListener(holder: ItemViewHolder, binding: ItemSearchListBinding) {
holder.itemView.setOnClickListener {
binding.cdRoot.setOnClickListener {
getItem(holder.layoutPosition)?.let {
if (it.query.isNotBlank()) callback.openSearchResult(it, holder.layoutPosition)
}
@@ -48,4 +51,4 @@ class SearchContentAdapter(context: Context, val callback: Callback) :
fun openSearchResult(searchResult: SearchResult, index: Int)
fun durChapterIndex(): Int
}
}
}
@@ -1,7 +1,13 @@
package io.legado.app.ui.book.searchContent
import android.text.Spanned
import androidx.core.text.HtmlCompat
import android.graphics.Typeface
import android.text.Spannable
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.text.style.UnderlineSpan
import io.legado.app.help.config.AppConfig
data class SearchResult(
@@ -17,44 +23,48 @@ data class SearchResult(
val queryIndexInChapter: Int = 0
) {
fun getHtmlCompat(textColor: String, accentColor: String): Spanned {
return if (query.isNotBlank()) {
val queryIndexInSurrounding = resultText.indexOf(query)
val leftString = resultText.substring(0, queryIndexInSurrounding)
val rightString =
resultText.substring(queryIndexInSurrounding + query.length, resultText.length)
// 检查是否为墨水屏模式
val html = if (AppConfig.isEInkMode) {
// 墨水屏模式:使用下划线
buildString {
append("<u>${chapterTitle}</u>")
append("<br>")
append(leftString)
append("<u>${query}</u>")
append(rightString)
}
} else {
// 普通模式:使用颜色
buildString {
append(chapterTitle.colorTextForHtml(accentColor))
append("<br>")
append(leftString.colorTextForHtml(textColor))
append(query.colorTextForHtml(accentColor))
append(rightString.colorTextForHtml(textColor))
}
fun getTitleSpannable(accentColor: Int): SpannableString {
return if (AppConfig.isEInkMode) {
SpannableString(chapterTitle).apply {
setSpan(UnderlineSpan(), 0, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY)
} else {
val html = if (AppConfig.isEInkMode) {
resultText
} else {
resultText.colorTextForHtml(textColor)
SpannableString(chapterTitle).apply {
setSpan(ForegroundColorSpan(accentColor), 0, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
}
private fun String.colorTextForHtml(textColor: String) =
"<font color=#${textColor}>$this</font>"
fun getContentSpannable(textColor: Int, accentColor: Int, bgColor: Int): SpannableStringBuilder {
val spannable = SpannableStringBuilder(resultText)
}
if (query.isNotBlank()) {
var searchStart = 0
while (true) {
val start = resultText.indexOf(query, searchStart, ignoreCase = true)
if (start == -1) break
val end = start + query.length
if (AppConfig.isEInkMode) {
spannable.setSpan(UnderlineSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
} else {
// 字体加粗
spannable.setSpan(StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
// 字体颜色
spannable.setSpan(ForegroundColorSpan(accentColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
// 背景色
spannable.setSpan(BackgroundColorSpan(bgColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
searchStart = end
}
}
// 设置整体字体颜色(正文)
if (!AppConfig.isEInkMode) {
spannable.setSpan(ForegroundColorSpan(textColor), 0, spannable.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
return spannable
}
}