HapeLee 1 год назад
Родитель
Сommit
8add267239

+ 0 - 7
app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt

@@ -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
     }
 

+ 12 - 9
app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentAdapter.kt

@@ -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
     }
-}
+}

+ 46 - 36
app/src/main/java/io/legado/app/ui/book/searchContent/SearchResult.kt

@@ -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
+    }
+}

+ 36 - 6
app/src/main/res/layout/item_search_list.xml

@@ -4,12 +4,42 @@
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:background="?attr/selectableItemBackground"
-    android:padding="16dp">
-
-    <TextView
-        android:id="@+id/tv_search_result"
+    android:layout_margin="8dp">
+    
+    <com.google.android.material.listitem.ListItemCardView
+        android:id="@+id/cd_root"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
+        android:layout_height="wrap_content"
+        android:checkable="true"
+        app:cardCornerRadius="16dp">
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:padding="8dp"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <TextView
+                android:id="@+id/tvTitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingBottom="2dp"
+                android:textColor="?attr/colorOnSurface"
+                android:textStyle="bold"
+                android:textSize="14sp"/>
+
+            <TextView
+                android:id="@+id/tvContent"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorOnSurface"
+                android:textSize="13sp"
+                android:lineSpacingExtra="2dp"/>
+
+        </LinearLayout>
+
+    </com.google.android.material.listitem.ListItemCardView>
+
+
 
 </LinearLayout>