更新界面

This commit is contained in:
HapeLee
2025-08-21 04:58:42 +08:00
parent ebc4135242
commit bf514ffd26
18 changed files with 230 additions and 154 deletions
@@ -5,6 +5,7 @@ import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.graphics.Paint import android.graphics.Paint
import android.graphics.Rect import android.graphics.Rect
import android.graphics.Typeface
import android.text.TextPaint import android.text.TextPaint
import android.view.View import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@@ -28,10 +29,11 @@ class BookmarkDecoration(
} }
private val textPaint = TextPaint().apply { private val textPaint = TextPaint().apply {
textSize = 16f.spToPx() textSize = 14f.spToPx()
color = color =
MaterialColors.getColor(context, androidx.appcompat.R.attr.colorPrimary, Color.BLACK) MaterialColors.getColor(context, androidx.appcompat.R.attr.colorPrimary, Color.BLACK)
isAntiAlias = true isAntiAlias = true
typeface = Typeface.DEFAULT_BOLD
} }
private val textRect = Rect() private val textRect = Rect()
@@ -8,6 +8,7 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.Looper import android.os.Looper
import android.view.Gravity import android.view.Gravity
import android.view.HapticFeedbackConstants
import android.view.InputDevice import android.view.InputDevice
import android.view.KeyEvent import android.view.KeyEvent
import android.view.Menu import android.view.Menu
@@ -788,21 +789,25 @@ class ReadBookActivity : BaseReadBookActivity(),
/** /**
* 更新文字选择开始位置 * 更新文字选择开始位置
*/ */
override fun upSelectedStart(x: Float, y: Float, top: Float) = binding.run { override fun upSelectedStart(x: Float, y: Float, top: Float): Unit = binding.run {
cursorLeft.x = x - cursorLeft.width cursorLeft.x = x - cursorLeft.width
cursorLeft.y = y cursorLeft.y = y
cursorLeft.visible(true) cursorLeft.visible(true)
textMenuPosition.x = x textMenuPosition.x = x
textMenuPosition.y = top textMenuPosition.y = top
root.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
} }
/** /**
* 更新文字选择结束位置 * 更新文字选择结束位置
*/ */
override fun upSelectedEnd(x: Float, y: Float) = binding.run { override fun upSelectedEnd(x: Float, y: Float): Unit = binding.run {
cursorRight.x = x cursorRight.x = x
cursorRight.y = y cursorRight.y = y
cursorRight.visible(true) cursorRight.visible(true)
root.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
} }
/** /**
@@ -32,12 +32,12 @@ class BookmarkAdapter(context: Context, val callback: Callback) :
override fun registerListener(holder: ItemViewHolder, binding: ItemBookmarkBinding) { override fun registerListener(holder: ItemViewHolder, binding: ItemBookmarkBinding) {
binding.root.setOnClickListener { binding.root.setOnClickListener {
getItem(holder.layoutPosition)?.let { bookmark -> getItem(holder.layoutPosition)?.let { bookmark ->
callback.onClick(bookmark) callback.onLongClick(bookmark, holder.layoutPosition)
} }
} }
binding.root.onLongClick { binding.root.onLongClick {
getItem(holder.layoutPosition)?.let { bookmark -> getItem(holder.layoutPosition)?.let { bookmark ->
callback.onLongClick(bookmark, holder.layoutPosition) callback.onClick(bookmark)
} }
} }
@@ -19,6 +19,7 @@ import io.legato.kazusa.ui.widget.recycler.VerticalDivider
import io.legato.kazusa.utils.applyNavigationBarPadding import io.legato.kazusa.utils.applyNavigationBarPadding
import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.showDialogFragment
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import io.legato.kazusa.utils.visible
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
@@ -51,24 +52,27 @@ class BookmarkFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_bookmark
binding.recyclerView.addItemDecoration(VerticalDivider(requireContext())) binding.recyclerView.addItemDecoration(VerticalDivider(requireContext()))
binding.recyclerView.adapter = adapter binding.recyclerView.adapter = adapter
binding.recyclerView.applyNavigationBarPadding() binding.recyclerView.applyNavigationBarPadding()
binding.tvEmptyMsg.visible(false)
} }
override fun upBookmark(searchKey: String?) { override fun upBookmark(searchKey: String?) {
val book = viewModel.bookData.value ?: return val book = viewModel.bookData.value ?: return
lifecycleScope.launch { lifecycleScope.launch {
when { val flow = when {
searchKey.isNullOrBlank() -> appDb.bookmarkDao.flowByBook(book.name, book.author) searchKey.isNullOrBlank() -> appDb.bookmarkDao.flowByBook(book.name, book.author)
else -> appDb.bookmarkDao.flowSearch(book.name, book.author, searchKey) else -> appDb.bookmarkDao.flowSearch(book.name, book.author, searchKey)
}.catch { }
flow.catch {
AppLog.put("目录界面获取书签数据失败\n${it.localizedMessage}", it) AppLog.put("目录界面获取书签数据失败\n${it.localizedMessage}", it)
}.flowOn(IO).collect { }.flowOn(IO).collect { list ->
adapter.setItems(it) adapter.setItems(list)
binding.tvEmptyMsg.visible(list.isEmpty())
var scrollPos = 0 var scrollPos = 0
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
adapter.getItems().forEachIndexed { index, bookmark -> adapter.getItems().forEachIndexed { index, bookmark ->
if (bookmark.chapterIndex >= durChapterIndex) { if (bookmark.chapterIndex >= durChapterIndex) return@withContext
return@withContext
}
scrollPos = index scrollPos = index
} }
} }
@@ -14,15 +14,17 @@ import io.legato.kazusa.data.entities.BookChapter
import io.legato.kazusa.databinding.ItemChapterListBinding import io.legato.kazusa.databinding.ItemChapterListBinding
import io.legato.kazusa.help.book.ContentProcessor import io.legato.kazusa.help.book.ContentProcessor
import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.help.coroutine.Coroutine
import io.legato.kazusa.lib.theme.ThemeUtils import io.legato.kazusa.lib.theme.ThemeUtils
import io.legato.kazusa.utils.gone import io.legato.kazusa.utils.gone
import io.legato.kazusa.utils.longToastOnUi import io.legato.kazusa.utils.longToastOnUi
import io.legato.kazusa.utils.themeColor import io.legato.kazusa.utils.themeColor
import io.legato.kazusa.utils.visible import io.legato.kazusa.utils.visible
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
class ChapterListAdapter(context: Context, val callback: Callback) : class ChapterListAdapter(context: Context, val callback: Callback) :
@@ -30,6 +32,7 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
val cacheFileNames = hashSetOf<String>() val cacheFileNames = hashSetOf<String>()
private val displayTitleMap = ConcurrentHashMap<String, String>() private val displayTitleMap = ConcurrentHashMap<String, String>()
private val handler = Handler(Looper.getMainLooper()) private val handler = Handler(Looper.getMainLooper())
override val diffItemCallback: DiffUtil.ItemCallback<BookChapter> override val diffItemCallback: DiffUtil.ItemCallback<BookChapter>
@@ -58,7 +61,7 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
} }
private var upDisplayTileJob: Coroutine<*>? = null private var upDisplayTileJob: Job? = null
override fun onCurrentListChanged() { override fun onCurrentListChanged() {
super.onCurrentListChanged() super.onCurrentListChanged()
@@ -72,42 +75,31 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
fun upDisplayTitles(startIndex: Int) { fun upDisplayTitles(startIndex: Int) {
upDisplayTileJob?.cancel() upDisplayTileJob?.cancel()
upDisplayTileJob = Coroutine.async(callback.scope) { upDisplayTileJob = callback.scope.launch(Dispatchers.Default) {
val book = callback.book ?: return@async val book = callback.book ?: return@launch
val replaceRules = ContentProcessor.get(book.name, book.origin).getTitleReplaceRules() val replaceRules = ContentProcessor.get(book.name, book.origin).getTitleReplaceRules()
val useReplace = AppConfig.tocUiUseReplace && book.getUseReplaceRule() val useReplace = AppConfig.tocUiUseReplace && book.getUseReplaceRule()
val items = getItems() val items = getItems()
launch {
for (i in startIndex until items.size) { val indices = (startIndex until items.size) + (startIndex downTo 0)
val item = items[i]
if (displayTitleMap[item.title] == null) { for (i in indices) {
ensureActive() val item = items[i]
val displayTitle = item.getDisplayTitle(replaceRules, useReplace) val key = item.url
ensureActive() if (displayTitleMap[key] == null) {
displayTitleMap[item.title] = displayTitle ensureActive()
handler.post { val displayTitle = item.getDisplayTitle(replaceRules, useReplace)
notifyItemChanged(i, true) displayTitleMap[key] = displayTitle
} ensureActive()
} withContext(Dispatchers.Main) {
} notifyItemChanged(i, true)
}
launch {
for (i in startIndex downTo 0) {
val item = items[i]
if (displayTitleMap[item.title] == null) {
ensureActive()
val displayTitle = item.getDisplayTitle(replaceRules, useReplace)
ensureActive()
displayTitleMap[item.title] = displayTitle
handler.post {
notifyItemChanged(i, true)
}
} }
} }
} }
} }
} }
private fun getDisplayTitle(chapter: BookChapter): String { private fun getDisplayTitle(chapter: BookChapter): String {
return displayTitleMap[chapter.title] ?: chapter.title return displayTitleMap[chapter.title] ?: chapter.title
} }
@@ -128,17 +120,22 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
|| item.isVolume || item.isVolume
|| cacheFileNames.contains(item.getFileName()) || cacheFileNames.contains(item.getFileName())
if (payloads.isEmpty()) { if (payloads.isEmpty()) {
if (isDur) {
tvChapterName.setTextColor(context.themeColor(androidx.appcompat.R.attr.colorPrimary))
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSurfaceContainer))
} else {
tvChapterName.setTextColor(context.themeColor(com.google.android.material.R.attr.colorOnSurface))
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSurface))
}
tvChapterName.text = getDisplayTitle(item)
if (item.isVolume) { if (item.isVolume) {
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSecondaryContainer)) ivVolume.visible()
tvChapterName.text = getDisplayTitle(item)
tvChapterName.textSize = 12f
tvChapterName.setTextColor(context.themeColor(com.google.android.material.R.attr.colorTertiary))
} else { } else {
ivVolume.gone()
if (isDur) {
tvChapterName.setTextColor(context.themeColor(androidx.appcompat.R.attr.colorPrimary))
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSurfaceContainer))
} else {
tvChapterName.setTextColor(context.themeColor(com.google.android.material.R.attr.colorOnSurface))
tvChapterItem.setBackgroundColor(context.themeColor(com.google.android.material.R.attr.colorSurface))
}
tvChapterName.text = getDisplayTitle(item)
tvChapterItem.foreground = tvChapterItem.foreground =
ThemeUtils.resolveDrawable(context, android.R.attr.selectableItemBackground) ThemeUtils.resolveDrawable(context, android.R.attr.selectableItemBackground)
} }
@@ -165,10 +162,10 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
ivLocked.gone() ivLocked.gone()
} }
upHasCache(binding, isDur, cached) upHasCache(binding, cached)
} else { } else {
tvChapterName.text = getDisplayTitle(item) tvChapterName.text = getDisplayTitle(item)
upHasCache(binding, isDur, cached) upHasCache(binding, cached)
} }
} }
} }
@@ -187,12 +184,11 @@ class ChapterListAdapter(context: Context, val callback: Callback) :
} }
} }
private fun upHasCache(binding: ItemChapterListBinding, isDur: Boolean, cached: Boolean) = private fun upHasCache(binding: ItemChapterListBinding, cached: Boolean) =
binding.apply { binding.apply {
when { when {
isDur -> ivChecked.gone()
cached -> { cached -> {
ivChecked.setImageResource(R.drawable.ic_check) ivChecked.setImageResource(R.drawable.ic_download_done)
ivChecked.visible() ivChecked.visible()
} }
@@ -1,7 +1,5 @@
package io.legato.kazusa.ui.book.toc package io.legato.kazusa.ui.book.toc
//import io.legado.app.lib.theme.bottomBackground
//import io.legado.app.lib.theme.getPrimaryTextColor
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity.RESULT_OK import android.app.Activity.RESULT_OK
import android.content.Intent import android.content.Intent
@@ -36,7 +34,6 @@ import io.legato.kazusa.utils.themeColor
import io.legato.kazusa.utils.toastOnUi import io.legato.kazusa.utils.toastOnUi
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.Default
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -79,7 +76,7 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
toastOnUi("开始下载: ${adapter.getItem(position)?.title}") toastOnUi("开始下载: ${adapter.getItem(position)?.title}")
CacheBook.start(requireContext(), book, chapter.index, chapter.index) CacheBook.start(requireContext(), book, chapter.index, chapter.index)
VibrationUtils.vibrate(context!!, 100) VibrationUtils.vibratePattern(requireContext(), longArrayOf(0, 50, 30, 50), -1)
adapter.notifyItemChanged(position) adapter.notifyItemChanged(position)
} }
@@ -191,16 +188,11 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
override fun observeLiveBus() { override fun observeLiveBus() {
observeEvent<Pair<Book, BookChapter>>(EventBus.SAVE_CONTENT) { (book, chapter) -> observeEvent<Pair<Book, BookChapter>>(EventBus.SAVE_CONTENT) { (book, chapter) ->
viewModel.bookData.value?.bookUrl?.let { bookUrl -> viewModel.bookData.value?.bookUrl?.let { bookUrl ->
if (book.bookUrl == bookUrl) { if (book.bookUrl == viewModel.bookData.value?.bookUrl) {
adapter.cacheFileNames.add(chapter.getFileName()) adapter.cacheFileNames.add(chapter.getFileName())
if (viewModel.searchKey.isNullOrEmpty()) { val index = adapter.getItems().indexOfFirst { it.index == chapter.index }
adapter.notifyItemChanged(chapter.index, true) if (index >= 0) {
} else { adapter.notifyItemChanged(index, true)
adapter.getItems().forEachIndexed { index, bookChapter ->
if (bookChapter.index == chapter.index) {
adapter.notifyItemChanged(index, true)
}
}
} }
} }
} }
@@ -225,15 +217,9 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
override fun onListChanged() { override fun onListChanged() {
lifecycleScope.launch { lifecycleScope.launch {
var scrollPos = 0 val scrollPos = adapter.getItems()
withContext(Default) { .indexOfLast { it.index < durChapterIndex }
adapter.getItems().forEachIndexed { index, bookChapter -> .coerceAtLeast(0)
if (bookChapter.index >= durChapterIndex) {
return@withContext
}
scrollPos = index
}
}
mLayoutManager.scrollToPositionWithOffset(scrollPos, 0) mLayoutManager.scrollToPositionWithOffset(scrollPos, 0)
adapter.upDisplayTitles(scrollPos) adapter.upDisplayTitles(scrollPos)
} }
@@ -60,8 +60,9 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
tabLayout = binding.tabLayout tabLayout = binding.tabLayout
binding.viewPager.adapter = TabFragmentPageAdapter() binding.viewPager.adapter = TabFragmentPageAdapter()
tabLayout.setupWithViewPager(binding.viewPager) tabLayout.setupWithViewPager(binding.viewPager)
viewModel.bookData.observe(this) { viewModel.bookData.observe(this) { book ->
menu?.setGroupVisible(R.id.menu_group_text, it.isLocalTxt) menu?.setGroupVisible(R.id.menu_group_text, book.isLocalTxt)
supportActionBar?.title = book.name
} }
intent.getStringExtra("bookUrl")?.let { intent.getStringExtra("bookUrl")?.let {
viewModel.initBook(it) viewModel.initBook(it)
+10 -6
View File
@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?><!-- res/drawable/md3_divider_inset.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android" <inset xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:insetLeft="16dp"
<size android:height="1px" /> android:insetRight="16dp">
<solid android:color="@color/bg_divider_line" /> <shape android:shape="rectangle">
</shape> <size android:height="1dp" />
<solid android:color="?attr/colorSurfaceContainer" />
</shape>
</inset>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M382,640L155,413L212,356L382,526L748,160L805,217L382,640ZM200,800L200,720L760,720L760,800L200,800Z" />
</vector>
@@ -19,7 +19,7 @@
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin" app:layout_collapseMode="pin"
app:navigationIcon="@drawable/ic_arrow_back" app:navigationIcon="@drawable/ic_arrow_back"
app:title="@string/chapter_list" /> app:title="" />
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout" android:id="@+id/tab_layout"
+2 -2
View File
@@ -78,7 +78,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Σ(#`O)" android:text="Σ(#`O)"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="24sp" /> android:textSize="32sp" />
<TextView <TextView
android:id="@+id/tv_msg" android:id="@+id/tv_msg"
@@ -90,7 +90,7 @@
android:id="@+id/tv_retry" android:id="@+id/tv_retry"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/Widget.Material3Expressive.Button.IconButton.Tonal" style="@style/Widget.Material3Expressive.Button.TonalButton"
app:icon="@drawable/ic_refresh" app:icon="@drawable/ic_refresh"
android:layout_margin="16dp" android:layout_margin="16dp"
app:iconPadding="4dp" app:iconPadding="4dp"
+28 -14
View File
@@ -9,18 +9,34 @@
android:orientation="vertical" android:orientation="vertical"
tools:ignore="UselessParent"> tools:ignore="UselessParent">
<androidx.appcompat.widget.Toolbar <LinearLayout
android:id="@+id/tool_bar" android:layout_width="match_parent"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingBottom="8dp">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:theme="?attr/actionBarStyle" android:layout_gravity="center_horizontal" />
app:title="@string/bookmark" />
<TextView
android:id="@+id/bottom_sheet_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/bookmark"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
<TextView <TextView
android:id="@+id/tv_chapter_name" android:id="@+id/tv_chapter_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="16dp" /> android:paddingHorizontal="16dp" />
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -36,8 +52,7 @@
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:paddingTop="3dp">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_book_text" android:id="@+id/edit_book_text"
@@ -74,11 +89,10 @@
<!-- 删除按钮靠左 --> <!-- 删除按钮靠左 -->
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_delete" android:id="@+id/btn_delete"
style="@style/Widget.Material3Expressive.Button.TonalButton" style="@style/Widget.Material3Expressive.Button.IconButton.Outlined"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="12dp" app:icon="@drawable/ic_clear_all"
android:text="@string/delete"
android:visibility="invisible" android:visibility="invisible"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@@ -90,7 +104,7 @@
style="@style/Widget.Material3Expressive.Button.TonalButton" style="@style/Widget.Material3Expressive.Button.TonalButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="12dp" android:minWidth="0dp"
android:text="@string/cancel" android:text="@string/cancel"
app:layout_constraintEnd_toStartOf="@id/btn_ok" app:layout_constraintEnd_toStartOf="@id/btn_ok"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@@ -100,10 +114,10 @@
<!-- 确认按钮靠右 --> <!-- 确认按钮靠右 -->
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btn_ok" android:id="@+id/btn_ok"
style="@style/Widget.Material3Expressive.Button.TonalButton" style="@style/Widget.Material3Expressive.Button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="12dp" android:minWidth="0dp"
android:text="@string/ok" android:text="@string/ok"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@@ -7,22 +7,20 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingHorizontal="16dp" android:paddingHorizontal="16dp"
android:paddingVertical="8dp"> android:paddingBottom="8dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:gravity="center" android:gravity="center"
android:paddingVertical="8dp" android:paddingBottom="8dp"
android:paddingHorizontal="16dp"> android:paddingHorizontal="16dp">
<View <com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:layout_width="36dp" android:layout_width="wrap_content"
android:layout_height="4dp" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal" />
android:background="@drawable/bg_bottom_sheet_handle"
android:layout_marginBottom="16dp" />
<TextView <TextView
android:id="@+id/bottom_sheet_title" android:id="@+id/bottom_sheet_title"
@@ -2,6 +2,7 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:descendantFocusability="blocksDescendants"> android:descendantFocusability="blocksDescendants">
<io.legato.kazusa.ui.widget.recycler.scroller.FastScrollRecyclerView <io.legato.kazusa.ui.widget.recycler.scroller.FastScrollRecyclerView
@@ -11,4 +12,31 @@
android:clipToPadding="false" android:clipToPadding="false"
android:overScrollMode="never" /> android:overScrollMode="never" />
<LinearLayout
android:id="@+id/tv_empty_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="16dp"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(๑`^´๑)"
android:textSize="32sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="还没有添加书签哦!" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
+1 -1
View File
@@ -30,7 +30,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="(๑`^´๑)" android:text="(๑`^´๑)"
android:textSize="30sp"/> android:textSize="32sp" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
+68 -42
View File
@@ -10,54 +10,80 @@
android:paddingHorizontal="16dp" android:paddingHorizontal="16dp"
android:paddingVertical="12dp"> android:paddingVertical="12dp">
<ImageView <LinearLayout
android:id="@+id/iv_locked" android:id="@+id/ll_info"
android:layout_width="24dp" android:layout_width="wrap_content"
android:layout_height="24dp" android:layout_height="wrap_content"
android:paddingEnd="8dp" android:gravity="center"
android:src="@drawable/ic_lock_outline"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_locked"
android:layout_width="24dp"
android:layout_height="24dp"
android:padding="4dp"
android:src="@drawable/ic_lock_outline"
android:visibility="visible" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/iv_volume"
android:layout_width="4dp"
android:layout_height="16dp"
android:layout_marginEnd="4dp"
android:visibility="visible"
app:cardBackgroundColor="?attr/colorTertiary"
app:strokeWidth="0dp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="4dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/iv_checked"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlSymmetry" /> app:layout_constraintStart_toEndOf="@id/ll_info">
<TextView <TextView
android:id="@+id/tv_chapter_name" android:id="@+id/tv_chapter_name"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="14sp" android:maxLines="2"
android:textStyle="bold" android:textSize="14sp"
android:maxLines="2" android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/iv_checked" app:layout_constraintEnd_toStartOf="@+id/iv_checked"
app:layout_constraintStart_toEndOf="@+id/iv_locked" app:layout_constraintStart_toEndOf="@+id/iv_locked"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/tv_word_count" android:id="@+id/tv_word_count"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:paddingEnd="18dp" android:paddingEnd="18dp"
android:singleLine="true" android:singleLine="true"
android:textSize="12sp" android:textSize="12sp"
android:visibility="gone" android:visibility="gone"
app:layout_constraintEnd_toStartOf="@+id/iv_checked" app:layout_constraintEnd_toStartOf="@+id/iv_checked"
app:layout_constraintStart_toEndOf="@+id/iv_locked" app:layout_constraintStart_toEndOf="@+id/iv_locked"
app:layout_constraintTop_toBottomOf="@id/tv_chapter_name" app:layout_constraintTop_toBottomOf="@id/tv_chapter_name"
tools:ignore="RtlSymmetry" /> tools:ignore="RtlSymmetry" />
<TextView <TextView
android:id="@+id/tv_tag" android:id="@+id/tv_tag"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:singleLine="true" android:singleLine="true"
android:textSize="12sp" android:textSize="12sp"
android:visibility="gone" android:visibility="gone"
app:layout_constraintEnd_toStartOf="@+id/iv_checked" app:layout_constraintEnd_toStartOf="@+id/iv_checked"
app:layout_constraintStart_toEndOf="@+id/iv_locked" app:layout_constraintStart_toEndOf="@+id/iv_locked"
app:layout_constraintTop_toBottomOf="@id/tv_word_count" /> app:layout_constraintTop_toBottomOf="@id/tv_word_count" />
</LinearLayout>
<ImageView <ImageView
android:id="@+id/iv_checked" android:id="@+id/iv_checked"
+1
View File
@@ -88,6 +88,7 @@
android:id="@+id/cd_count" android:id="@+id/cd_count"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginVertical="4dp" android:layout_marginVertical="4dp"
app:cardBackgroundColor="?attr/colorSurfaceContainer" app:cardBackgroundColor="?attr/colorSurfaceContainer"
app:cardCornerRadius="4dp" app:cardCornerRadius="4dp"
+1 -1
View File
@@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.google.android.material.progressindicator.CircularProgressIndicator <com.google.android.material.loadingindicator.LoadingIndicator
android:id="@+id/rotate_loading" android:id="@+id/rotate_loading"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"