更新界面

This commit is contained in:
HapeLee committed 2025-07-04 15:23:28 +08:00
1 parent ea36e85899
commit 9f5a0eb483
36 files changed
+1358 -974

No files matched your search

@@ -85,6 +85,9 @@ interface BookGroupDao {
@Delete @Delete
fun delete(vararg bookGroup: BookGroup) fun delete(vararg bookGroup: BookGroup)
@Query("UPDATE book_groups SET cover = NULL WHERE groupId = :groupId")
fun clearCover(groupId: Long)
fun isInRules(id: Long): Boolean { fun isInRules(id: Long): Boolean {
if (id < 0) { if (id < 0) {
return true return true
@@ -18,7 +18,6 @@ class NameListPreference(context: Context, attrs: AttributeSet) : ListPreference
init { init {
layoutResource = R.layout.view_preference layoutResource = R.layout.view_preference
widgetLayoutResource = R.layout.item_fillet_text
context.withStyledAttributes(attrs, R.styleable.Preference) { context.withStyledAttributes(attrs, R.styleable.Preference) {
isBottomBackground = getBoolean(R.styleable.Preference_isBottomBackground, false) isBottomBackground = getBoolean(R.styleable.Preference_isBottomBackground, false)
} }
@@ -26,16 +25,16 @@ class NameListPreference(context: Context, attrs: AttributeSet) : ListPreference
override fun onBindViewHolder(holder: PreferenceViewHolder) { override fun onBindViewHolder(holder: PreferenceViewHolder) {
val v = Preference.bindView<TextView>( val v = Preference.bindView<TextView>(
context, holder, icon, title, summary, widgetLayoutResource, context, holder, icon, title, entry,
R.id.text_view, isBottomBackground = isBottomBackground R.id.text_view, isBottomBackground = isBottomBackground
) )
if (v is TextView) { if (v is TextView) {
v.text = entry v.text = entry
if (isBottomBackground) { // if (isBottomBackground) {
// val bgColor = context.bottomBackground // val bgColor = context.bottomBackground
// val pTextColor = context.getPrimaryTextColor(ColorUtils.isColorLight(bgColor)) // val pTextColor = context.getPrimaryTextColor(ColorUtils.isColorLight(bgColor))
//v.setTextColor(pTextColor) // //v.setTextColor(pTextColor)
} // }
} }
super.onBindViewHolder(holder) super.onBindViewHolder(holder)
} }
@@ -67,7 +67,8 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
bookGroup?.let { bookGroup?.let {
binding.btnDelete.visible(it.groupId > 0 || it.groupId == Long.MIN_VALUE) binding.btnDelete.visible(it.groupId > 0 || it.groupId == Long.MIN_VALUE)
binding.tieGroupName.setText(it.groupName) binding.tieGroupName.setText(it.groupName)
binding.ivCover.load(it.cover) if (bookGroup?.cover != null)
binding.ivCover.load(it.cover)
binding.spSort.setSelection(it.bookSort + 1) binding.spSort.setSelection(it.bookSort + 1)
binding.cbEnableRefresh.isChecked = it.enableRefresh binding.cbEnableRefresh.isChecked = it.enableRefresh
} ?: let { } ?: let {
@@ -79,6 +80,14 @@ class GroupEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_book_gro
ivCover.onClick { ivCover.onClick {
selectImage.launch() selectImage.launch()
} }
btnReset.onClick {
bookGroup?.let {
viewModel.clearCover(it) {
toastOnUi("封面已重置")
dismiss()
}
}
}
btnCancel.onClick { btnCancel.onClick {
dismiss() dismiss()
} }
@@ -48,5 +48,12 @@ class GroupViewModel(application: Application) : BaseViewModel(application) {
} }
} }
fun clearCover(bookGroup: BookGroup, finally: () -> Unit) {
execute {
appDb.bookGroupDao.clearCover(bookGroup.groupId)
}.onFinally {
finally()
}
}
} }
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.drawable.GradientDrawable import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE import android.view.WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
import android.view.animation.Animation import android.view.animation.Animation
@@ -19,19 +18,10 @@ import io.legato.kazusa.constant.PreferKey
import io.legato.kazusa.databinding.ViewReadMenuBinding import io.legato.kazusa.databinding.ViewReadMenuBinding
import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.help.config.LocalConfig import io.legato.kazusa.help.config.LocalConfig
import io.legato.kazusa.help.config.ReadBookConfig
import io.legato.kazusa.help.config.ThemeConfig
import io.legato.kazusa.help.coroutine.Coroutine import io.legato.kazusa.help.coroutine.Coroutine
import io.legato.kazusa.help.source.getSourceType import io.legato.kazusa.help.source.getSourceType
import io.legato.kazusa.lib.dialogs.alert import io.legato.kazusa.lib.dialogs.alert
//import io.legado.app.lib.theme.accentColor
//import io.legado.app.lib.theme.bottomBackground
//import io.legado.app.lib.theme.buttonDisabledColor
//import io.legado.app.lib.theme.getPrimaryTextColor
//import io.legado.app.lib.theme.primaryColor
//import io.legado.app.lib.theme.primaryTextColor
import io.legato.kazusa.model.ReadBook import io.legato.kazusa.model.ReadBook
import io.legato.kazusa.ui.book.read.config.MoreConfigDialog
import io.legato.kazusa.ui.browser.WebViewActivity import io.legato.kazusa.ui.browser.WebViewActivity
import io.legato.kazusa.ui.widget.seekbar.SeekBarChangeListener import io.legato.kazusa.ui.widget.seekbar.SeekBarChangeListener
import io.legato.kazusa.utils.ConstraintModify import io.legato.kazusa.utils.ConstraintModify
@@ -45,7 +35,6 @@ import io.legato.kazusa.utils.loadAnimation
import io.legato.kazusa.utils.modifyBegin import io.legato.kazusa.utils.modifyBegin
import io.legato.kazusa.utils.openUrl import io.legato.kazusa.utils.openUrl
import io.legato.kazusa.utils.putPrefBoolean import io.legato.kazusa.utils.putPrefBoolean
import io.legato.kazusa.utils.showDialogFragment
import io.legato.kazusa.utils.startActivity import io.legato.kazusa.utils.startActivity
import io.legato.kazusa.utils.visible import io.legato.kazusa.utils.visible
import splitties.views.onClick import splitties.views.onClick
@@ -75,8 +64,8 @@ class ReadMenu @JvmOverloads constructor(
private val menuBottomOut: Animation by lazy { private val menuBottomOut: Animation by lazy {
loadAnimation(context, R.anim.anim_readbook_bottom_out) loadAnimation(context, R.anim.anim_readbook_bottom_out)
} }
private val immersiveMenu: Boolean // private val immersiveMenu: Boolean
get() = AppConfig.readBarStyleFollowPage && ReadBookConfig.durConfig.curBgType() == 0 // get() = AppConfig.readBarStyleFollowPage && ReadBookConfig.durConfig.curBgType() == 0
// private var bgColor: Int = if (immersiveMenu) { // private var bgColor: Int = if (immersiveMenu) {
// kotlin.runCatching { // kotlin.runCatching {
// ReadBookConfig.durConfig.curBgStr().toColorInt() // ReadBookConfig.durConfig.curBgStr().toColorInt()
@@ -160,29 +149,29 @@ class ReadMenu @JvmOverloads constructor(
bindEvent() bindEvent()
} }
private fun initView(reset: Boolean = false) = binding.run { private fun initView() = binding.run {
// if (AppConfig.isNightTheme) { // if (AppConfig.isNightTheme) {
// fabNightTheme.setIconResource(R.drawable.ic_daytime) // fabNightTheme.setIconResource(R.drawable.ic_daytime)
// } else { // } else {
// fabNightTheme.setIconResource(R.drawable.ic_brightness) // fabNightTheme.setIconResource(R.drawable.ic_brightness)
// } // }
initAnimation() initAnimation()
if (immersiveMenu) { // if (immersiveMenu) {
// val lightTextColor = ColorUtils.withAlpha(ColorUtils.lightenColor(textColor), 0.75f) //// val lightTextColor = ColorUtils.withAlpha(ColorUtils.lightenColor(textColor), 0.75f)
// titleBar.setTextColor(textColor) //// titleBar.setTextColor(textColor)
// titleBar.setBackgroundColor(bgColor) //// titleBar.setBackgroundColor(bgColor)
// titleBar.setColorFilter(textColor) //// titleBar.setColorFilter(textColor)
// tvChapterName.setTextColor(lightTextColor) //// tvChapterName.setTextColor(lightTextColor)
// tvChapterUrl.setTextColor(lightTextColor) //// tvChapterUrl.setTextColor(lightTextColor)
} else if (reset) { // } else if (reset) {
// val bgColor = context.primaryColor //// val bgColor = context.primaryColor
// val textColor = context.primaryTextColor //// val textColor = context.primaryTextColor
// titleBar.setTextColor(textColor) //// titleBar.setTextColor(textColor)
// titleBar.setBackgroundColor(bgColor) //// titleBar.setBackgroundColor(bgColor)
// titleBar.setColorFilter(textColor) //// titleBar.setColorFilter(textColor)
// tvChapterName.setTextColor(textColor) //// tvChapterName.setTextColor(textColor)
// tvChapterUrl.setTextColor(textColor) //// tvChapterUrl.setTextColor(textColor)
} // }
val brightnessBackground = GradientDrawable() val brightnessBackground = GradientDrawable()
brightnessBackground.cornerRadius = 5F.dpToPx() brightnessBackground.cornerRadius = 5F.dpToPx()
//brightnessBackground.setColor(ColorUtils.adjustAlpha(bgColor, 0.5f)) //brightnessBackground.setColor(ColorUtils.adjustAlpha(bgColor, 0.5f))
@@ -230,13 +219,13 @@ class ReadMenu @JvmOverloads constructor(
fun reset() { fun reset() {
upColorConfig() upColorConfig()
initView(true) initView()
} }
fun refreshMenuColorFilter() { fun refreshMenuColorFilter() {
if (immersiveMenu) { // if (immersiveMenu) {
//binding.titleBar.setColorFilter(textColor) // //binding.titleBar.setColorFilter(textColor)
} // }
} }
private fun upColorConfig() { private fun upColorConfig() {
@@ -514,8 +503,6 @@ class ReadMenu @JvmOverloads constructor(
fun upSeekBar() { fun upSeekBar() {
binding.seekReadPage.apply { binding.seekReadPage.apply {
Log.d("SliderDebug", "durPageIndex: ${ReadBook.durPageIndex}, pageSize: ${ReadBook.curTextChapter?.pageSize}")
Log.d("SliderDebug", "durChapterIndex: ${ReadBook.durChapterIndex}, simulatedChapterSize: ${ReadBook.simulatedChapterSize}")
when (AppConfig.progressBarBehavior) { when (AppConfig.progressBarBehavior) {
"page" -> { "page" -> {
ReadBook.curTextChapter?.let { chapter -> ReadBook.curTextChapter?.let { chapter ->
@@ -9,7 +9,6 @@ import android.view.MenuItem
import android.view.MotionEvent import android.view.MotionEvent
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.addCallback import androidx.activity.addCallback
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.postDelayed import androidx.core.view.postDelayed
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@@ -33,7 +32,6 @@ import io.legato.kazusa.help.config.LocalConfig
import io.legato.kazusa.help.coroutine.Coroutine import io.legato.kazusa.help.coroutine.Coroutine
import io.legato.kazusa.help.storage.Backup import io.legato.kazusa.help.storage.Backup
import io.legato.kazusa.lib.dialogs.alert import io.legato.kazusa.lib.dialogs.alert
//import io.legado.app.lib.theme.primaryColor
import io.legato.kazusa.service.BaseReadAloudService import io.legato.kazusa.service.BaseReadAloudService
import io.legato.kazusa.ui.about.CrashLogsDialog import io.legato.kazusa.ui.about.CrashLogsDialog
import io.legato.kazusa.ui.main.bookshelf.BaseBookshelfFragment import io.legato.kazusa.ui.main.bookshelf.BaseBookshelfFragment
@@ -45,9 +43,7 @@ import io.legato.kazusa.ui.main.rss.RssFragment
import io.legato.kazusa.ui.widget.dialog.TextDialog import io.legato.kazusa.ui.widget.dialog.TextDialog
import io.legato.kazusa.utils.hideSoftInput import io.legato.kazusa.utils.hideSoftInput
import io.legato.kazusa.utils.isCreated import io.legato.kazusa.utils.isCreated
import io.legato.kazusa.utils.navigationBarHeight
import io.legato.kazusa.utils.observeEvent import io.legato.kazusa.utils.observeEvent
import io.legato.kazusa.utils.setOnApplyWindowInsetsListenerCompat
import io.legato.kazusa.utils.shouldHideSoftInput import io.legato.kazusa.utils.shouldHideSoftInput
import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.showDialogFragment
import io.legato.kazusa.utils.toastOnUi import io.legato.kazusa.utils.toastOnUi
@@ -55,14 +51,11 @@ import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import splitties.views.bottomPadding
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
import androidx.core.view.get import androidx.core.view.get
import com.google.android.material.navigation.NavigationBarView import com.google.android.material.navigation.NavigationBarView
import io.legato.kazusa.ui.welcome.WelcomeActivity import io.legato.kazusa.ui.main.bookshelf.style1.BookshelfFragment3
import io.legato.kazusa.utils.applyNavigationBarPadding
import io.legato.kazusa.utils.applyStatusBarPadding
/** /**
* 主界面 * 主界面
@@ -76,6 +69,7 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
private val idBookshelf = 0 private val idBookshelf = 0
private val idBookshelf1 = 11 private val idBookshelf1 = 11
private val idBookshelf2 = 12 private val idBookshelf2 = 12
private val idBookshelf3 = 13
private val idExplore = 1 private val idExplore = 1
private val idRss = 2 private val idRss = 2
private val idMy = 3 private val idMy = 3
@@ -424,11 +418,17 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
private fun getFragmentId(position: Int): Int { private fun getFragmentId(position: Int): Int {
val id = realPositions[position] val id = realPositions[position]
if (id == idBookshelf) { if (id == idBookshelf) {
return if (AppConfig.bookGroupStyle == 1) idBookshelf2 else idBookshelf1 return when (AppConfig.bookGroupStyle) {
0 -> idBookshelf1
1 -> idBookshelf2
2 -> idBookshelf3
else -> idBookshelf1
}
} }
return id return id
} }
private inner class PageChangeCallback : ViewPager.SimpleOnPageChangeListener() { private inner class PageChangeCallback : ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
@@ -447,24 +447,28 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
} }
override fun getItemPosition(any: Any): Int { override fun getItemPosition(any: Any): Int {
val position = (any as MainFragmentInterface).position val position = (any as? MainFragmentInterface)?.position ?: return POSITION_NONE
?: return POSITION_NONE
val fragmentId = getId(position) val fragmentId = getId(position)
if ((fragmentId == idBookshelf1 && any is BookshelfFragment1)
|| (fragmentId == idBookshelf2 && any is BookshelfFragment2) if (
|| (fragmentId == idExplore && any is ExploreFragment) (fragmentId == idBookshelf1 && any is BookshelfFragment1) ||
|| (fragmentId == idRss && any is RssFragment) (fragmentId == idBookshelf2 && any is BookshelfFragment2) ||
|| (fragmentId == idMy && any is MyFragment) (fragmentId == idBookshelf3 && any is BookshelfFragment3) ||
(fragmentId == idExplore && any is ExploreFragment) ||
(fragmentId == idRss && any is RssFragment) ||
(fragmentId == idMy && any is MyFragment)
) { ) {
return POSITION_UNCHANGED return POSITION_UNCHANGED
} }
return POSITION_NONE return POSITION_NONE
} }
override fun getItem(position: Int): Fragment { override fun getItem(position: Int): Fragment {
return when (getId(position)) { return when (getId(position)) {
idBookshelf1 -> BookshelfFragment1(position) idBookshelf1 -> BookshelfFragment1(position)
idBookshelf2 -> BookshelfFragment2(position) idBookshelf2 -> BookshelfFragment2(position)
idBookshelf3 -> BookshelfFragment3(position)
idExplore -> ExploreFragment(position) idExplore -> ExploreFragment(position)
idRss -> RssFragment(position) idRss -> RssFragment(position)
else -> MyFragment(position) else -> MyFragment(position)
@@ -4,10 +4,12 @@ import android.annotation.SuppressLint
import android.content.res.Configuration import android.content.res.Configuration
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import com.google.android.material.chip.Chip
import io.legato.kazusa.R import io.legato.kazusa.R
import io.legato.kazusa.base.VMBaseFragment import io.legato.kazusa.base.VMBaseFragment
import io.legato.kazusa.constant.EventBus import io.legato.kazusa.constant.EventBus
@@ -30,9 +32,6 @@ import io.legato.kazusa.ui.file.HandleFileContract
import io.legato.kazusa.ui.main.MainFragmentInterface import io.legato.kazusa.ui.main.MainFragmentInterface
import io.legato.kazusa.ui.main.MainViewModel import io.legato.kazusa.ui.main.MainViewModel
import io.legato.kazusa.ui.widget.dialog.WaitDialog import io.legato.kazusa.ui.widget.dialog.WaitDialog
import io.legato.kazusa.utils.bookshelfLayout
import io.legato.kazusa.utils.checkByIndex
import io.legato.kazusa.utils.getCheckedIndex
import io.legato.kazusa.utils.isAbsUrl import io.legato.kazusa.utils.isAbsUrl
import io.legato.kazusa.utils.postEvent import io.legato.kazusa.utils.postEvent
import io.legato.kazusa.utils.readText import io.legato.kazusa.utils.readText
@@ -166,7 +165,7 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment<BookshelfVi
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
fun configBookshelf() { fun configBookshelf() {
alert(titleResource = R.string.bookshelf_layout) { alert {
val orientation = requireContext().resources.configuration.orientation val orientation = requireContext().resources.configuration.orientation
val bookshelfLayout = if (orientation == Configuration.ORIENTATION_LANDSCAPE) { val bookshelfLayout = if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
@@ -182,20 +181,53 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment<BookshelfVi
val alertBinding = val alertBinding =
DialogBookshelfConfigBinding.inflate(layoutInflater) DialogBookshelfConfigBinding.inflate(layoutInflater)
.apply { .apply {
spGroupStyle.setSelection(AppConfig.bookGroupStyle)
val groupStyleArray = resources.getStringArray(R.array.group_style)
val chipGroupStyle = chipGroupStyle
groupStyleArray.forEachIndexed { index, label ->
val chip = Chip(context).apply {
text = label
isCheckable = true
isClickable = true
id = View.generateViewId()
}
chipGroupStyle.addView(chip)
if (index == AppConfig.bookGroupStyle) {
chipGroupStyle.check(chip.id)
}
}
val sortArray = resources.getStringArray(R.array.bookshelf_px_array)
val chipGroupSort = chipGroupSort
sortArray.forEachIndexed { index, label ->
val chip = Chip(context).apply {
text = label
isCheckable = true
isClickable = true
id = View.generateViewId()
}
chipGroupSort.addView(chip)
if (index == AppConfig.bookshelfSort) {
chipGroupSort.check(chip.id)
}
}
swShowUnread.isChecked = AppConfig.showUnread swShowUnread.isChecked = AppConfig.showUnread
swShowLastUpdateTime.isChecked = AppConfig.showLastUpdateTime swShowLastUpdateTime.isChecked = AppConfig.showLastUpdateTime
swShowWaitUpBooks.isChecked = AppConfig.showWaitUpCount swShowWaitUpBooks.isChecked = AppConfig.showWaitUpCount
swShowBookshelfFastScroller.isChecked = AppConfig.showBookshelfFastScroller swShowBookshelfFastScroller.isChecked = AppConfig.showBookshelfFastScroller
rgSort.checkByIndex(bookshelfSort)
chipList.isChecked = !isGrid chipList.isChecked = !isGrid
chipGrid.isChecked = isGrid chipGrid.isChecked = isGrid
llGridSlider.isVisible = isGrid sliderText.isVisible = isGrid
sliderGridCount.isVisible = isGrid
sliderGridCount.value = columnCount.toFloat() sliderGridCount.value = columnCount.toFloat()
chipGroupLayout.setOnCheckedChangeListener { _, checkedId -> chipGroupLayout.setOnCheckedStateChangeListener { group, checkedIds ->
llGridSlider.isVisible = checkedId == R.id.chip_grid sliderText.isVisible = checkedIds.firstOrNull() == R.id.chip_grid
sliderGridCount.isVisible = checkedIds.firstOrNull() == R.id.chip_grid
} }
} }
@@ -205,10 +237,12 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment<BookshelfVi
alertBinding.apply { alertBinding.apply {
var notifyMain = false var notifyMain = false
var recreate = false var recreate = false
if (AppConfig.bookGroupStyle != spGroupStyle.selectedItemPosition) {
AppConfig.bookGroupStyle = spGroupStyle.selectedItemPosition if (AppConfig.bookGroupStyle != chipGroupStyle.checkedChipId) {
AppConfig.bookGroupStyle = chipGroupStyle.indexOfChild(chipGroupStyle.findViewById(chipGroupStyle.checkedChipId))
notifyMain = true notifyMain = true
} }
if (AppConfig.showUnread != swShowUnread.isChecked) { if (AppConfig.showUnread != swShowUnread.isChecked) {
AppConfig.showUnread = swShowUnread.isChecked AppConfig.showUnread = swShowUnread.isChecked
postEvent(EventBus.BOOKSHELF_REFRESH, "") postEvent(EventBus.BOOKSHELF_REFRESH, "")
@@ -225,8 +259,8 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment<BookshelfVi
AppConfig.showBookshelfFastScroller = swShowBookshelfFastScroller.isChecked AppConfig.showBookshelfFastScroller = swShowBookshelfFastScroller.isChecked
postEvent(EventBus.BOOKSHELF_REFRESH, "") postEvent(EventBus.BOOKSHELF_REFRESH, "")
} }
if (bookshelfSort != rgSort.getCheckedIndex()) { if (bookshelfSort != chipGroupSort.indexOfChild(chipGroupSort.findViewById(chipGroupSort.checkedChipId))) {
AppConfig.bookshelfSort = rgSort.getCheckedIndex() AppConfig.bookshelfSort = chipGroupSort.indexOfChild(chipGroupSort.findViewById(chipGroupSort.checkedChipId))
upSort() upSort()
} }
@@ -5,11 +5,8 @@ package io.legato.kazusa.ui.main.bookshelf.style1
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
@@ -19,13 +16,10 @@ import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.data.entities.BookGroup import io.legato.kazusa.data.entities.BookGroup
import io.legato.kazusa.databinding.FragmentBookshelf1Binding import io.legato.kazusa.databinding.FragmentBookshelf1Binding
import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.config.AppConfig
//import io.legado.app.lib.theme.accentColor
//import io.legado.app.lib.theme.primaryColor
import io.legato.kazusa.ui.book.group.GroupEditDialog import io.legato.kazusa.ui.book.group.GroupEditDialog
import io.legato.kazusa.ui.book.search.SearchActivity import io.legato.kazusa.ui.book.search.SearchActivity
import io.legato.kazusa.ui.main.bookshelf.BaseBookshelfFragment import io.legato.kazusa.ui.main.bookshelf.BaseBookshelfFragment
import io.legato.kazusa.ui.main.bookshelf.style1.books.BooksFragment import io.legato.kazusa.ui.main.bookshelf.style1.books.BooksFragment
import io.legato.kazusa.utils.isCreated
import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.showDialogFragment
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
@@ -45,9 +39,7 @@ class BookshelfFragment1() : BaseBookshelfFragment(R.layout.fragment_bookshelf1)
} }
private val binding by viewBinding(FragmentBookshelf1Binding::bind) private val binding by viewBinding(FragmentBookshelf1Binding::bind)
private val tabLayout: TabLayout by lazy {
binding.tabLayout.findViewById(R.id.tab_layout)
}
private val bookGroups = mutableListOf<BookGroup>() private val bookGroups = mutableListOf<BookGroup>()
private val fragmentMap = hashMapOf<Long, BooksFragment>() private val fragmentMap = hashMapOf<Long, BooksFragment>()
override val groupId: Long get() = selectedGroup?.groupId ?: 0 override val groupId: Long get() = selectedGroup?.groupId ?: 0
@@ -0,0 +1,144 @@
@file:Suppress("DEPRECATION")
package io.legato.kazusa.ui.main.bookshelf.style1
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.tabs.TabLayout
import io.legato.kazusa.R
import io.legato.kazusa.data.appDb
import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.data.entities.BookGroup
import io.legato.kazusa.databinding.FragmentBookshelf3Binding
import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.ui.book.search.SearchActivity
import io.legato.kazusa.ui.main.bookshelf.BaseBookshelfFragment
import io.legato.kazusa.ui.main.bookshelf.style1.books.BooksFragment
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import kotlin.collections.set
/**
* 书架界面
*/
class BookshelfFragment3() : BaseBookshelfFragment(R.layout.fragment_bookshelf3),
TabLayout.OnTabSelectedListener,
SearchView.OnQueryTextListener {
constructor(position: Int) : this() {
val bundle = Bundle()
bundle.putInt("position", position)
arguments = bundle
}
private val binding by viewBinding(FragmentBookshelf3Binding::bind)
private val bookGroups = mutableListOf<BookGroup>()
private val fragmentMap = hashMapOf<Long, BooksFragment>()
override val groupId: Long get() = selectedGroup?.groupId ?: 0
private lateinit var adapter: TabFragmentPageAdapter
override val books: List<Book>
get() {
val fragment = fragmentMap[groupId]
return fragment?.getBooks() ?: emptyList()
}
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
setSupportToolbar(binding.topBar)
initView()
initBookGroupData()
}
private val selectedGroup: BookGroup?
get() = bookGroups.getOrNull(binding.viewPagerBookshelf.currentItem)
private fun initView() {
adapter = TabFragmentPageAdapter(this)
binding.viewPagerBookshelf.adapter = adapter
binding.viewPagerBookshelf.offscreenPageLimit = 1
binding.viewPagerBookshelf.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
updateToolbarTitle(position)
}
})
}
private fun updateToolbarTitle(position: Int) {
if (bookGroups.isNotEmpty() && position in 0 until bookGroups.size) {
binding.collTopBar.title = bookGroups[position].groupName
}
}
override fun onQueryTextSubmit(query: String?): Boolean {
SearchActivity.start(requireContext(), query)
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
return false
}
@SuppressLint("NotifyDataSetChanged")
@Synchronized
override fun upGroup(data: List<BookGroup>) {
if (data.isEmpty()) {
appDb.bookGroupDao.enableGroup(BookGroup.IdAll)
} else {
if (data != bookGroups) {
bookGroups.clear()
bookGroups.addAll(data)
adapter.notifyDataSetChanged()
adapter = TabFragmentPageAdapter(this)
binding.viewPagerBookshelf.adapter = adapter
updateToolbarTitle(binding.viewPagerBookshelf.currentItem)
}
}
}
override fun upSort() {
childFragmentManager.fragments.forEach {
if (it is BooksFragment) {
val position = it.position
val group = bookGroups.getOrNull(position) ?: return@forEach
val newSort = group.getRealBookSort()
it.setEnableRefresh(group.enableRefresh)
if (it.bookSort != newSort) {
it.upBookSort(newSort)
}
}
}
}
override fun onTabReselected(tab: TabLayout.Tab) {
}
override fun onTabUnselected(tab: TabLayout.Tab) = Unit
override fun onTabSelected(tab: TabLayout.Tab) {
AppConfig.saveTabPosition = tab.position
}
override fun gotoTop() {
fragmentMap[groupId]?.gotoTop()
}
private inner class TabFragmentPageAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
override fun getItemCount(): Int = bookGroups.size
override fun createFragment(position: Int): Fragment {
val group = bookGroups[position]
val fragment = BooksFragment(position, group)
fragmentMap[group.groupId] = fragment
return fragment
}
}
}
@@ -3,6 +3,7 @@ package io.legato.kazusa.ui.main.bookshelf.style1.books
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import io.legato.kazusa.base.adapter.ItemViewHolder import io.legato.kazusa.base.adapter.ItemViewHolder
@@ -10,7 +11,6 @@ import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.databinding.ItemBookshelfListBinding import io.legato.kazusa.databinding.ItemBookshelfListBinding
import io.legato.kazusa.help.book.isLocal import io.legato.kazusa.help.book.isLocal
import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.utils.invisible
import io.legato.kazusa.utils.toTimeAgo import io.legato.kazusa.utils.toTimeAgo
import splitties.views.onLongClick import splitties.views.onLongClick
@@ -68,15 +68,16 @@ class BooksAdapterList(
private fun upRefresh(binding: ItemBookshelfListBinding, item: Book) { private fun upRefresh(binding: ItemBookshelfListBinding, item: Book) {
if (!item.isLocal && callBack.isUpdate(item.bookUrl)) { if (!item.isLocal && callBack.isUpdate(item.bookUrl)) {
binding.bvUnread.invisible() binding.tvUnread.isVisible = false
binding.rlLoading.visible() binding.rlLoading.isVisible = true
} else { } else {
binding.rlLoading.gone() binding.rlLoading.isVisible = false
if (AppConfig.showUnread) { if (AppConfig.showUnread) {
binding.bvUnread.setHighlight(item.lastCheckCount > 0) //binding.tvUnread.setHighlight(item.lastCheckCount > 0)
binding.bvUnread.setBadgeCount(item.getUnreadChapterNum()) binding.tvUnread.isVisible = true
binding.tvUnread.text = item.getUnreadChapterNum().toString()
} else { } else {
binding.bvUnread.invisible() binding.tvUnread.isVisible = false
} }
} }
} }
@@ -94,13 +95,13 @@ class BooksAdapterList(
override fun registerListener(holder: ItemViewHolder, binding: ItemBookshelfListBinding) { override fun registerListener(holder: ItemViewHolder, binding: ItemBookshelfListBinding) {
holder.itemView.apply { holder.itemView.apply {
setOnClickListener { binding.cvContent.setOnClickListener {
getItem(holder.layoutPosition)?.let { getItem(holder.layoutPosition)?.let {
callBack.open(it) callBack.open(it)
} }
} }
onLongClick { binding.cvContent.onLongClick {
getItem(holder.layoutPosition)?.let { getItem(holder.layoutPosition)?.let {
callBack.openBookInfo(it) callBack.openBookInfo(it)
} }
@@ -46,10 +46,7 @@ abstract class BaseBooksAdapter<VH : RecyclerView.ViewHolder>(
oldItem.getUnreadChapterNum() == newItem.getUnreadChapterNum() oldItem.getUnreadChapterNum() == newItem.getUnreadChapterNum()
} }
oldItem is BookGroup && newItem is BookGroup -> { oldItem is BookGroup && newItem is BookGroup -> false
oldItem.groupName == newItem.groupName &&
oldItem.cover == newItem.cover
}
else -> false else -> false
} }
@@ -120,6 +117,12 @@ abstract class BaseBooksAdapter<VH : RecyclerView.ViewHolder>(
fun getItem(position: Int) = getItems().getOrNull(position) fun getItem(position: Int) = getItems().getOrNull(position)
internal var allBooks: List<Book> = emptyList()
fun setAllBooks(all: List<Book>) {
this.allBooks = all
}
override fun getItemCount(): Int { override fun getItemCount(): Int {
return getItems().size return getItems().size
} }
@@ -4,13 +4,16 @@ import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.legato.kazusa.R
import io.legato.kazusa.data.entities.Book import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.data.entities.BookGroup import io.legato.kazusa.data.entities.BookGroup
import io.legato.kazusa.databinding.ItemBookshelfGridBinding import io.legato.kazusa.databinding.ItemBookshelfGridBinding
import io.legato.kazusa.databinding.ItemBookshelfGridGroupBinding import io.legato.kazusa.databinding.ItemBookshelfGridGroupBinding
import io.legato.kazusa.help.book.isLocal import io.legato.kazusa.help.book.isLocal
import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.utils.gone
import splitties.views.onLongClick import splitties.views.onLongClick
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
@@ -32,31 +35,40 @@ class BooksAdapterGrid(context: Context, callBack: CallBack) :
position: Int, position: Int,
payloads: MutableList<Any> payloads: MutableList<Any>
) { ) {
when (holder) { when (holder) {
is BookViewHolder -> (getItem(position) as? Book)?.let { is BookViewHolder -> (getItem(position) as? Book)?.let {
holder.registerListener(it) holder.registerListener(it)
holder.onBind(it, position, payloads) holder.onBind(it, payloads)
} }
is GroupViewHolder -> (getItem(position) as? BookGroup)?.let { is GroupViewHolder -> (getItem(position) as? BookGroup)?.let {
holder.registerListener(it) holder.registerListener(it)
holder.onBind(it, position, payloads) holder.onBind(it, payloads)
} }
} }
} }
private fun getBooksForGroup(group: BookGroup): List<Book> {
return if (group.groupId == -1L) {
allBooks.take(4)
} else {
allBooks.filter { (it.group and group.groupId) != 0L }.take(4)
}
}
inner class BookViewHolder(val binding: ItemBookshelfGridBinding) : inner class BookViewHolder(val binding: ItemBookshelfGridBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
fun onBind(item: Book, position: Int) = binding.run { fun onBind(item: Book) = binding.run {
tvName.text = item.name tvName.text = item.name
ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin) ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin)
upRefresh(this, item) upRefresh(this, item)
} }
fun onBind(item: Book, position: Int, payloads: MutableList<Any>) = binding.run { fun onBind(item: Book, payloads: MutableList<Any>) = binding.run {
if (payloads.isEmpty()) { if (payloads.isEmpty()) {
onBind(item, position) onBind(item)
} else { } else {
for (i in payloads.indices) { for (i in payloads.indices) {
val bundle = payloads[i] as Bundle val bundle = payloads[i] as Bundle
@@ -79,10 +91,10 @@ class BooksAdapterGrid(context: Context, callBack: CallBack) :
} }
fun registerListener(item: Any) { fun registerListener(item: Any) {
binding.root.setOnClickListener { binding.cvContent.setOnClickListener {
callBack.onItemClick(item) callBack.onItemClick(item)
} }
binding.root.onLongClick { binding.cvContent.onLongClick {
callBack.onItemLongClick(item) callBack.onItemLongClick(item)
} }
} }
@@ -113,21 +125,22 @@ class BooksAdapterGrid(context: Context, callBack: CallBack) :
inner class GroupViewHolder(val binding: ItemBookshelfGridGroupBinding) : inner class GroupViewHolder(val binding: ItemBookshelfGridGroupBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
fun onBind(item: BookGroup, position: Int) = binding.run { fun onBind(item: BookGroup) = binding.run {
tvName.text = item.groupName tvName.text = item.groupName
ivCover.load(item.cover) loadGroupCover(item)
cdUnread.gone()
} }
fun onBind(item: BookGroup, position: Int, payloads: MutableList<Any>) = binding.run { fun onBind(item: BookGroup, payloads: MutableList<Any>) = binding.run {
if (payloads.isEmpty()) { if (payloads.isEmpty()) {
onBind(item, position) onBind(item)
} else { } else {
for (i in payloads.indices) { for (i in payloads.indices) {
val bundle = payloads[i] as Bundle val bundle = payloads[i] as Bundle
bundle.keySet().forEach { bundle.keySet().forEach {
when (it) { when (it) {
"groupName" -> tvName.text = item.groupName "groupName" -> tvName.text = item.groupName
"cover" -> ivCover.load(item.cover) "cover" -> loadGroupCover(item)
} }
} }
} }
@@ -143,6 +156,28 @@ class BooksAdapterGrid(context: Context, callBack: CallBack) :
} }
} }
private fun loadGroupCover(item: BookGroup) = binding.run {
binding.ivCover.setImageDrawable(
ContextCompat.getDrawable(binding.root.context, R.drawable.bg_surface_variant)
)
binding.ivCover1.setImageDrawable(null)
binding.ivCover2.setImageDrawable(null)
binding.ivCover3.setImageDrawable(null)
binding.ivCover4.setImageDrawable(null)
if (!item.cover.isNullOrEmpty()) {
ivCover.load(item.cover)
} else {
val books = getBooksForGroup(item)
if (books.size > 0) binding.ivCover1.load(books[0].getDisplayCover())
if (books.size > 1) binding.ivCover2.load(books[1].getDisplayCover())
if (books.size > 2) binding.ivCover3.load(books[2].getDisplayCover())
if (books.size > 3) binding.ivCover4.load(books[3].getDisplayCover())
}
}
} }
} }
@@ -3,7 +3,10 @@ package io.legato.kazusa.ui.main.bookshelf.style2
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.legato.kazusa.R
import io.legato.kazusa.data.entities.Book import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.data.entities.BookGroup import io.legato.kazusa.data.entities.BookGroup
import io.legato.kazusa.databinding.ItemBookshelfListBinding import io.legato.kazusa.databinding.ItemBookshelfListBinding
@@ -11,7 +14,7 @@ import io.legato.kazusa.databinding.ItemBookshelfListGroupBinding
import io.legato.kazusa.help.book.isLocal import io.legato.kazusa.help.book.isLocal
import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.utils.gone import io.legato.kazusa.utils.gone
import io.legato.kazusa.utils.invisible import io.legato.kazusa.utils.toTimeAgo
import io.legato.kazusa.utils.visible import io.legato.kazusa.utils.visible
import splitties.views.onLongClick import splitties.views.onLongClick
@@ -34,35 +37,44 @@ class BooksAdapterList(context: Context, callBack: CallBack) :
when (holder) { when (holder) {
is BookViewHolder -> (getItem(position) as? Book)?.let { is BookViewHolder -> (getItem(position) as? Book)?.let {
holder.registerListener(it) holder.registerListener(it)
holder.onBind(it, position, payloads) holder.onBind(it, payloads)
} }
is GroupViewHolder -> (getItem(position) as? BookGroup)?.let { is GroupViewHolder -> (getItem(position) as? BookGroup)?.let {
holder.registerListener(it) holder.registerListener(it)
holder.onBind(it, position, payloads) holder.onBind(it, payloads)
} }
} }
} }
private fun getBooksForGroup(group: BookGroup): List<Book> {
return if (group.groupId == -1L) {
allBooks.take(4)
} else {
allBooks.filter { (it.group and group.groupId) != 0L }.take(4)
}
}
inner class BookViewHolder(val binding: ItemBookshelfListBinding) : inner class BookViewHolder(val binding: ItemBookshelfListBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
fun onBind(item: Book, position: Int) = binding.run { fun onBind(item: Book) = binding.run {
tvName.text = item.name tvName.text = item.name
tvAuthor.text = item.author tvAuthor.text = item.author
tvRead.text = item.durChapterTitle tvRead.text = item.durChapterTitle
tvLast.text = item.latestChapterTitle tvLast.text = item.latestChapterTitle
ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin) ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin)
flHasNew.visible() cdUnread.visible()
ivAuthor.visible() ivAuthor.visible()
ivLast.visible() ivLast.visible()
ivRead.visible() ivRead.visible()
upRefresh(this, item) upRefresh(this, item)
upLastUpdateTime(binding, item)
} }
fun onBind(item: Book, position: Int, payloads: MutableList<Any>) = binding.run { fun onBind(item: Book, payloads: MutableList<Any>) = binding.run {
if (payloads.isEmpty()) { if (payloads.isEmpty()) {
onBind(item, position) onBind(item)
} else { } else {
for (i in payloads.indices) { for (i in payloads.indices) {
val bundle = payloads[i] as Bundle val bundle = payloads[i] as Bundle
@@ -81,32 +93,45 @@ class BooksAdapterList(context: Context, callBack: CallBack) :
) )
"refresh" -> upRefresh(this, item) "refresh" -> upRefresh(this, item)
"lastUpdateTime" -> upLastUpdateTime(binding, item)
} }
} }
} }
} }
} }
private fun upLastUpdateTime(binding: ItemBookshelfListBinding, item: Book) {
if (AppConfig.showLastUpdateTime && !item.isLocal) {
val time = item.latestChapterTime.toTimeAgo()
if (binding.tvLastUpdateTime.text != time) {
binding.tvLastUpdateTime.text = time
}
} else {
binding.tvLastUpdateTime.text = ""
}
}
fun registerListener(item: Any) { fun registerListener(item: Any) {
binding.root.setOnClickListener { binding.cvContent.setOnClickListener {
callBack.onItemClick(item) callBack.onItemClick(item)
} }
binding.root.onLongClick { binding.cvContent.onLongClick {
callBack.onItemLongClick(item) callBack.onItemLongClick(item)
} }
} }
private fun upRefresh(binding: ItemBookshelfListBinding, item: Book) { private fun upRefresh(binding: ItemBookshelfListBinding, item: Book) {
if (!item.isLocal && callBack.isUpdate(item.bookUrl)) { if (!item.isLocal && callBack.isUpdate(item.bookUrl)) {
binding.bvUnread.invisible() binding.tvUnread.isVisible = false
binding.rlLoading.visible() binding.rlLoading.isVisible = true
} else { } else {
binding.rlLoading.gone() binding.rlLoading.isVisible = false
if (AppConfig.showUnread) { if (AppConfig.showUnread) {
binding.bvUnread.setHighlight(item.lastCheckCount > 0) //binding.tvUnread.setHighlight(item.lastCheckCount > 0)
binding.bvUnread.setBadgeCount(item.getUnreadChapterNum()) binding.tvUnread.isVisible = true
binding.tvUnread.text = item.getUnreadChapterNum().toString()
} else { } else {
binding.bvUnread.invisible() binding.tvUnread.isVisible = false
} }
} }
} }
@@ -116,28 +141,23 @@ class BooksAdapterList(context: Context, callBack: CallBack) :
inner class GroupViewHolder(val binding: ItemBookshelfListGroupBinding) : inner class GroupViewHolder(val binding: ItemBookshelfListGroupBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
fun onBind(item: BookGroup, position: Int) = binding.run { fun onBind(item: BookGroup) = binding.run {
tvName.text = item.groupName tvName.text = item.groupName
ivCover.load(item.cover) loadGroupCover(item)
flHasNew.gone() cdUnread.gone()
ivAuthor.gone()
ivLast.gone()
ivRead.gone()
tvAuthor.gone()
tvLast.gone()
tvRead.gone()
} }
fun onBind(item: BookGroup, position: Int, payloads: MutableList<Any>) = binding.run {
fun onBind(item: BookGroup, payloads: MutableList<Any>) = binding.run {
if (payloads.isEmpty()) { if (payloads.isEmpty()) {
onBind(item, position) onBind(item)
} else { } else {
for (i in payloads.indices) { for (i in payloads.indices) {
val bundle = payloads[i] as Bundle val bundle = payloads[i] as Bundle
bundle.keySet().forEach { bundle.keySet().forEach {
when (it) { when (it) {
"groupName" -> tvName.text = item.groupName "groupName" -> tvName.text = item.groupName
"cover" -> ivCover.load(item.cover) "cover" -> loadGroupCover(item)
} }
} }
} }
@@ -145,14 +165,36 @@ class BooksAdapterList(context: Context, callBack: CallBack) :
} }
fun registerListener(item: Any) { fun registerListener(item: Any) {
binding.root.setOnClickListener { binding.cvContent.setOnClickListener {
callBack.onItemClick(item) callBack.onItemClick(item)
} }
binding.root.onLongClick { binding.cvContent.onLongClick {
callBack.onItemLongClick(item) callBack.onItemLongClick(item)
} }
} }
private fun loadGroupCover(item: BookGroup) = binding.run {
binding.ivCover.setImageDrawable(
ContextCompat.getDrawable(binding.root.context, R.drawable.bg_surface_variant)
)
binding.ivCover1.setImageDrawable(null)
binding.ivCover2.setImageDrawable(null)
binding.ivCover3.setImageDrawable(null)
binding.ivCover4.setImageDrawable(null)
if (!item.cover.isNullOrEmpty()) {
ivCover.load(item.cover)
} else {
val books = getBooksForGroup(item)
if (books.size > 0) binding.ivCover1.load(books[0].getDisplayCover())
if (books.size > 1) binding.ivCover2.load(books[1].getDisplayCover())
if (books.size > 2) binding.ivCover3.load(books[2].getDisplayCover())
if (books.size > 3) binding.ivCover4.load(books[3].getDisplayCover())
}
}
} }
} }
@@ -7,6 +7,7 @@ import androidx.appcompat.widget.SearchView
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@@ -19,8 +20,6 @@ import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.data.entities.BookGroup import io.legato.kazusa.data.entities.BookGroup
import io.legato.kazusa.databinding.FragmentBookshelf2Binding import io.legato.kazusa.databinding.FragmentBookshelf2Binding
import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.config.AppConfig
//import io.legado.app.lib.theme.accentColor
//import io.legado.app.lib.theme.primaryColor
import io.legato.kazusa.ui.book.group.GroupEditDialog import io.legato.kazusa.ui.book.group.GroupEditDialog
import io.legato.kazusa.ui.book.info.BookInfoActivity import io.legato.kazusa.ui.book.info.BookInfoActivity
import io.legato.kazusa.ui.book.search.SearchActivity import io.legato.kazusa.ui.book.search.SearchActivity
@@ -35,7 +34,6 @@ import io.legato.kazusa.utils.startActivityForBook
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
@@ -67,9 +65,11 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
BooksAdapterGrid(requireContext(), this) BooksAdapterGrid(requireContext(), this)
} }
} }
private var bookGroups: List<BookGroup> = emptyList() private var bookGroups: List<BookGroup> = emptyList()
private var booksFlowJob: Job? = null private var booksFlowJob: Job? = null
override var groupId = BookGroup.IdRoot override var groupId = BookGroup.IdRoot
private var allBooks: List<Book> = emptyList()
override var books: List<Book> = emptyList() override var books: List<Book> = emptyList()
private var enableRefresh = true private var enableRefresh = true
@@ -77,12 +77,11 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
setSupportToolbar(binding.titleBar.toolbar) setSupportToolbar(binding.titleBar.toolbar)
initRecyclerView() initRecyclerView()
initBookGroupData() initBookGroupData()
initAllBooksData()
initBooksData() initBooksData()
} }
private fun initRecyclerView() { private fun initRecyclerView() {
// binding.rvBookshelf.setEdgeEffectColor(primaryColor)
// binding.refreshLayout.setColorSchemeColors(accentColor)
binding.refreshLayout.setOnRefreshListener { binding.refreshLayout.setOnRefreshListener {
binding.refreshLayout.isRefreshing = false binding.refreshLayout.isRefreshing = false
activityViewModel.upToc(books) activityViewModel.upToc(books)
@@ -111,6 +110,7 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
} }
} }
}) })
binding.rvBookshelf.itemAnimator = DefaultItemAnimator()
} }
override fun upGroup(data: List<BookGroup>) { override fun upGroup(data: List<BookGroup>) {
@@ -123,9 +123,37 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
} }
override fun upSort() { override fun upSort() {
initAllBooksData()
initBooksData() initBooksData()
} }
private var allBooksFlowJob: Job? = null
private fun initAllBooksData() {
allBooksFlowJob?.cancel()
allBooksFlowJob = viewLifecycleOwner.lifecycleScope.launch {
appDb.bookDao.flowAll().map { list ->
when (AppConfig.getBookSortByGroupId(BookGroup.IdRoot)) {
1 -> list.sortedByDescending { it.latestChapterTime }
2 -> list.sortedWith { o1, o2 -> o1.name.cnCompare(o2.name) }
3 -> list.sortedBy { it.order }
4 -> list.sortedByDescending { max(it.latestChapterTime, it.durChapterTime) }
else -> list.sortedByDescending { it.durChapterTime }
}
}.flowWithLifecycleAndDatabaseChangeFirst(
viewLifecycleOwner.lifecycle,
Lifecycle.State.RESUMED,
AppDatabase.BOOK_TABLE_NAME
).catch {
AppLog.put("所有书籍更新出错", it)
}.conflate().flowOn(Dispatchers.Default).collect { list ->
allBooks = list
booksAdapter.setAllBooks(allBooks)
booksAdapter.updateItems()
}
}
}
private fun initBooksData() { private fun initBooksData() {
if (groupId == BookGroup.IdRoot) { if (groupId == BookGroup.IdRoot) {
if (isAdded) { if (isAdded) {
@@ -137,14 +165,16 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
bookGroups.firstOrNull { bookGroups.firstOrNull {
groupId == it.groupId groupId == it.groupId
}?.let { }?.let {
binding.titleBar.title = "${getString(R.string.bookshelf)}(${it.groupName})" binding.titleBar.title = it.groupName
binding.refreshLayout.isEnabled = it.enableRefresh binding.refreshLayout.isEnabled = it.enableRefresh
enableRefresh = it.enableRefresh enableRefresh = it.enableRefresh
} }
} }
booksFlowJob?.cancel() booksFlowJob?.cancel()
booksFlowJob = viewLifecycleOwner.lifecycleScope.launch { booksFlowJob = viewLifecycleOwner.lifecycleScope.launch {
appDb.bookDao.flowByGroup(groupId).map { list -> appDb.bookDao.flowByGroup(groupId).map { list ->
//排序 //排序
when (AppConfig.getBookSortByGroupId(groupId)) { when (AppConfig.getBookSortByGroupId(groupId)) {
1 -> list.sortedByDescending { 1 -> list.sortedByDescending {
@@ -178,7 +208,6 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
booksAdapter.updateItems() booksAdapter.updateItems()
binding.tvEmptyMsg.isGone = getItemCount() > 0 binding.tvEmptyMsg.isGone = getItemCount() > 0
binding.refreshLayout.isEnabled = enableRefresh && getItemCount() > 0 binding.refreshLayout.isEnabled = enableRefresh && getItemCount() > 0
delay(100)
} }
} }
} }
@@ -244,12 +273,14 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
} }
override fun getItems(): List<Any> { override fun getItems(): List<Any> {
if (groupId != BookGroup.IdRoot) { return if (groupId == BookGroup.IdRoot) {
return books bookGroups + books
} else {
books
} }
return bookGroups + books
} }
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
override fun observeLiveBus() { override fun observeLiveBus() {
super.observeLiveBus() super.observeLiveBus()
@@ -2,11 +2,10 @@ package io.legato.kazusa.ui.widget
import android.content.Context import android.content.Context
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Color
import android.util.AttributeSet import android.util.AttributeSet
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import com.google.android.material.color.MaterialColors import io.legato.kazusa.utils.themeColor
@Suppress("unused", "MemberVisibilityCanBePrivate") @Suppress("unused", "MemberVisibilityCanBePrivate")
class LabelsBar @JvmOverloads constructor( class LabelsBar @JvmOverloads constructor(
@@ -44,10 +43,9 @@ class LabelsBar @JvmOverloads constructor(
chipStrokeWidth = 0f chipStrokeWidth = 0f
chipBackgroundColor = ColorStateList.valueOf( chipBackgroundColor = ColorStateList.valueOf(
MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimaryContainer, Color.LTGRAY) context.themeColor(com.google.android.material.R.attr.colorPrimaryContainer)
) )
usedChips.add(this) usedChips.add(this)
} }
} else { } else {
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" <set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="320" android:duration="280"
android:interpolator="@android:interpolator/decelerate_cubic"> android:interpolator="@android:interpolator/decelerate_cubic">
<translate <translate
android:fromYDelta="100%" android:fromYDelta="100%"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" <set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="320" android:duration="280"
android:interpolator="@android:interpolator/decelerate_cubic"> android:interpolator="@android:interpolator/decelerate_cubic">
<translate <translate
android:fromYDelta="-100%" android:fromYDelta="-100%"
+1 -1
View File
@@ -2,5 +2,5 @@
<!-- res/drawable/bg_semi_transparent_overlay.xml --> <!-- res/drawable/bg_semi_transparent_overlay.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<solid android:color="@color/transparent70" /> <solid android:color="@color/transparent50" />
</shape> </shape>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable/bg_semi_transparent_overlay.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/transparent70" />
</shape>
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--实现应用背景颜色渐变-->
<gradient
android:startColor="#000000"
android:endColor="#00000000"
android:angle="90" />
</shape>
@@ -2,7 +2,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<solid android:color="?attr/colorSurfaceContainer" /> <solid android:color="?attr/colorSurface" />
<corners <corners
android:topLeftRadius="16dp" android:topLeftRadius="16dp"
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="?attr/colorSurfaceContainerHigh" />
</shape>
@@ -10,7 +10,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/bg_image" android:contentDescription="@string/bg_image"
android:foreground="@drawable/bg_book_mask" android:foreground="@drawable/bg_book_mask_land"
android:scaleType="centerCrop" /> android:scaleType="centerCrop" />
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
@@ -45,306 +45,317 @@
android:layout_height="match_parent" android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:id="@+id/scroll_view"
android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal"> android:layout_weight="2"
android:fillViewport="true"
android:fitsSystemWindows="false"
android:focusable="true"
android:padding="0dp"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:baselineAligned="false"
android:paddingHorizontal="32dp" android:orientation="horizontal">
tools:ignore="RtlSymmetry">
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="120dp"
android:layout_marginStart="16dp"
android:layout_marginVertical="16dp"
app:cardCornerRadius="16dp">
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover"
android:layout_width="150dp"
android:layout_height="210dp"
android:contentDescription="@string/img_cover"
android:scaleType="centerCrop"
android:src="@drawable/image_cover_default" />
</androidx.cardview.widget.CardView>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_weight="1"
android:orientation="vertical" android:orientation="vertical"
android:padding="12dp"> android:paddingHorizontal="32dp"
tools:ignore="RtlSymmetry">
<TextView <androidx.cardview.widget.CardView
android:id="@+id/tv_name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/book_name" android:layout_marginTop="16dp"
style="@style/TextAppearance.Material3.ActionBar.Title" android:layout_marginStart="32dp"
tools:ignore="RtlHardcoded" /> app:cardCornerRadius="16dp">
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover"
android:layout_width="150dp"
android:layout_height="210dp"
android:contentDescription="@string/img_cover"
android:scaleType="centerCrop"
android:src="@drawable/image_cover_default" />
</androidx.cardview.widget.CardView>
<LinearLayout <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:paddingTop="6dp"
android:paddingBottom="2dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="18sp"
android:layout_height="18sp"
android:contentDescription="@string/author"
android:src="@drawable/ic_author"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_author"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="2dp"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/author"
android:textSize="14sp"
tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_web"
android:layout_width="18sp"
android:layout_height="18sp"
android:contentDescription="@string/origin_format"
android:src="@drawable/ic_web_outline"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_origin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="2dp"
android:ellipsize="end"
android:paddingRight="6dp"
android:singleLine="true"
android:textSize="14sp"
tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry"
tools:text="@string/origin_format" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:fillViewport="true"
android:fitsSystemWindows="false"
android:focusable="true"
android:padding="0dp"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical">
<LinearLayout
android:id="@+id/ll_info"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@drawable/bg_gradient_mask_land" android:layout_gravity="center"
android:orientation="vertical" android:orientation="vertical"
android:layout_marginStart="16dp" android:paddingTop="16dp"
android:padding="8dp"> android:paddingHorizontal="30dp">
<HorizontalScrollView <TextView
android:layout_width="match_parent" android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:text="@string/book_name"
android:scrollbars="none"> style="@style/TextAppearance.Material3.ActionBar.Title"
tools:ignore="RtlHardcoded" />
<io.legato.kazusa.ui.widget.LabelsBar
android:id="@+id/lb_kind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible" />
</HorizontalScrollView>
<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:gravity="center"
android:paddingHorizontal="8dp" android:orientation="horizontal"
android:paddingBottom="8dp"> android:paddingTop="6dp"
android:paddingBottom="2dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="18sp"
android:layout_height="18sp"
android:contentDescription="@string/author"
android:src="@drawable/ic_author"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_author"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="2dp"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/author"
android:textSize="14sp"
tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_web"
android:layout_width="18sp"
android:layout_height="18sp"
android:contentDescription="@string/origin_format"
android:src="@drawable/ic_web_outline"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_origin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="2dp"
android:ellipsize="end"
android:paddingRight="6dp"
android:singleLine="true"
android:textSize="14sp"
tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry"
tools:text="@string/origin_format" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_info"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="@drawable/bg_gradient_mask_land"
android:orientation="vertical"
android:padding="8dp">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:scrollbars="none">
<io.legato.kazusa.ui.widget.LabelsBar
android:id="@+id/lb_kind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible" />
</HorizontalScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="8dp"
android:paddingBottom="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_shelf"
style="@style/Widget.Material3.Button.TonalButton"
android:backgroundTint="?attr/colorSurfaceContainer"
app:cornerRadius="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:padding="8dp"
android:text="@string/remove_from_bookshelf"
android:textSize="13sp"
app:icon="@drawable/ic_clear_all"
app:iconGravity="top"
app:iconPadding="4dp"
app:iconSize="20dp" />
<!-- 查看目录按钮 -->
<com.google.android.material.button.MaterialButton
android:id="@+id/tv_toc_view"
style="@style/Widget.Material3.Button.TonalButton"
android:backgroundTint="?attr/colorSurfaceContainer"
app:cornerRadius="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:padding="8dp"
android:text="@string/view_toc"
android:textSize="13sp"
app:icon="@drawable/ic_toc"
app:iconGravity="top"
app:iconPadding="4dp"
app:iconSize="20dp" />
<!-- 更换分组按钮 -->
<com.google.android.material.button.MaterialButton
android:id="@+id/tv_change_group"
style="@style/Widget.Material3.Button.TonalButton"
android:backgroundTint="?attr/colorSurfaceContainer"
app:cornerRadius="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:padding="8dp"
android:text="@string/change_group"
android:textSize="13sp"
app:icon="@drawable/ic_groups"
app:iconGravity="top"
app:iconPadding="4dp"
app:iconSize="20dp" />
<!-- 更换来源按钮(保持原样) -->
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_change_source"
style="@style/Widget.Material3.Button.TonalButton"
android:backgroundTint="?attr/colorSurfaceContainer"
app:cornerRadius="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/book_source"
android:padding="8dp"
app:icon="@drawable/ic_change_source"
android:textSize="13sp"
app:iconGravity="top"
app:iconPadding="4dp"
app:iconSize="20dp"
tools:contentDescription="@string/change_origin" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="16dp"
android:paddingHorizontal="2dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_toc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="6dp"
android:textSize="16sp"
android:textStyle="bold"
tools:text="@string/toc_s" />
<TextView
android:id="@+id/tv_lasted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="6dp"
android:singleLine="true"
android:textSize="14sp"
tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry"
tools:text="@string/read_dur_progress" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_shelf"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:padding="8dp"
android:text="@string/remove_from_bookshelf"
android:textSize="13sp"
app:icon="@drawable/ic_clear_all"
app:iconGravity="top"
app:iconPadding="4dp"
app:iconSize="20dp" />
<!-- 查看目录按钮 -->
<com.google.android.material.button.MaterialButton
android:id="@+id/tv_toc_view"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:padding="8dp"
android:text="@string/view_toc"
android:textSize="13sp"
app:icon="@drawable/ic_toc"
app:iconGravity="top"
app:iconPadding="4dp"
app:iconSize="20dp" />
<!-- 更换分组按钮 -->
<com.google.android.material.button.MaterialButton
android:id="@+id/tv_change_group"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:padding="8dp"
android:text="@string/change_group"
android:textSize="13sp"
app:icon="@drawable/ic_groups"
app:iconGravity="top"
app:iconPadding="4dp"
app:iconSize="20dp" />
<!-- 更换来源按钮(保持原样) -->
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_change_source"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/book_source"
android:padding="8dp"
app:icon="@drawable/ic_change_source"
android:textSize="13sp"
app:iconGravity="top"
app:iconPadding="4dp"
app:iconSize="20dp"
tools:contentDescription="@string/change_origin" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="8dp"
android:paddingHorizontal="2dp"
android:orientation="vertical">
<TextView <TextView
android:id="@+id/tv_toc" android:id="@+id/tv_chapter"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="6dp" android:textColor="?attr/colorPrimary"
android:textSize="16sp" android:singleLine="true"
android:paddingEnd="8dp"
android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
tools:text="@string/toc_s" /> tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry"
tools:text="@string/read_chapter_total" />
<TextView <TextView
android:id="@+id/tv_lasted" android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="|"
android:textColor="?attr/colorSecondary"
android:layout_marginEnd="8dp"/>
<TextView
android:id="@+id/tv_chapter_index"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="6dp" android:textColor="?attr/colorSecondary"
android:singleLine="true" android:singleLine="true"
android:textSize="14sp" android:textSize="14sp"
tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry" tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry"
tools:text="@string/read_dur_progress" /> tools:text="@string/read_chapter_index"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_chapter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/colorSecondaryVariant"
android:singleLine="true"
android:paddingEnd="8dp"
android:textSize="14sp"
android:textStyle="bold"
tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry"
tools:text="@string/read_chapter_total" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="|"
android:textColor="?attr/colorSecondary"
android:layout_marginEnd="8dp"/>
<TextView
android:id="@+id/tv_chapter_index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/colorSecondary"
android:singleLine="true"
android:textSize="14sp"
tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry"
tools:text="@string/read_chapter_index"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<TextView
android:id="@+id/tv_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginHorizontal="8dp"
android:clickable="true"
android:focusable="true"
android:minHeight="48dp"
android:paddingBottom="80dp"
android:lineSpacingExtra="4dp"
android:text="@string/book_intro"
android:textIsSelectable="true"
android:textSize="14sp"
android:visibility="visible"
tools:ignore="RtlHardcoded,RtlSymmetry" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout> <TextView
android:id="@+id/tv_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginHorizontal="8dp"
android:clickable="true"
android:focusable="true"
android:minHeight="48dp"
android:paddingBottom="80dp"
android:lineSpacingExtra="4dp"
android:text="@string/book_intro"
android:textIsSelectable="true"
android:textSize="14sp"
android:visibility="visible"
tools:ignore="RtlHardcoded,RtlSymmetry" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
@@ -22,8 +22,8 @@
<com.google.android.material.appbar.CollapsingToolbarLayout <com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize" android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
style="?attr/collapsingToolbarLayoutLargeSize" style="?attr/collapsingToolbarLayoutMediumStyle"
app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge" app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge"
app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge" app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
@@ -275,7 +275,6 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="6dp" android:paddingBottom="6dp"
android:singleLine="true"
android:textSize="14sp" android:textSize="14sp"
tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry" tools:ignore="NestedWeights,RtlHardcoded,RtlSymmetry"
tools:text="@string/read_dur_progress" /> tools:text="@string/read_dur_progress" />
@@ -289,7 +288,7 @@
android:id="@+id/tv_chapter" android:id="@+id/tv_chapter"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="?attr/colorSecondaryVariant" android:textColor="?attr/colorPrimaryVariant"
android:singleLine="true" android:singleLine="true"
android:paddingEnd="8dp" android:paddingEnd="8dp"
android:textSize="14sp" android:textSize="14sp"
@@ -19,7 +19,7 @@
<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="horizontal"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:padding="16dp"> android:padding="16dp">
@@ -30,7 +30,7 @@
android:layout_margin="8dp" android:layout_margin="8dp"
android:contentDescription="@string/img_cover" android:contentDescription="@string/img_cover"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:src="@drawable/image_cover_default" android:src="?attr/colorSurfaceVariant"
tools:ignore="ImageContrastCheck" /> tools:ignore="ImageContrastCheck" />
<LinearLayout <LinearLayout
@@ -80,6 +80,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/allow_drop_down_refresh" android:text="@string/allow_drop_down_refresh"
android:checked="true" /> android:checked="true" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@@ -95,10 +96,18 @@
android:id="@+id/btn_delete" android:id="@+id/btn_delete"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.OutlinedButton" style="@style/Widget.Material3.Button.IconButton.Outlined"
android:text="@string/delete" android:layout_marginEnd="4dp"
app:icon="@drawable/ic_clear_all"
tools:ignore="RtlHardcoded" /> tools:ignore="RtlHardcoded" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_reset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:icon="@drawable/ic_restore"
style="@style/Widget.Material3.Button.IconButton.Outlined"/>
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="1dp" android:layout_height="1dp"
@@ -109,7 +118,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.TonalButton" style="@style/Widget.Material3.Button.TonalButton"
android:layout_marginEnd="8dp" android:layout_marginEnd="4dp"
android:text="@string/cancel" /> android:text="@string/cancel" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
@@ -9,14 +9,21 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bookshelf_layout"
android:layout_marginVertical="8dp"
style="@style/ChapterNameText"/>
<com.google.android.material.materialswitch.MaterialSwitch <com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sw_show_unread" android:id="@+id/sw_show_unread"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="8dp"
android:text="@string/show_unread" android:text="@string/show_unread"
tools:ignore="TouchTargetSizeCheck" /> tools:ignore="TouchTargetSizeCheck" />
@@ -24,7 +31,6 @@
android:id="@+id/sw_show_last_update_time" android:id="@+id/sw_show_last_update_time"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="8dp"
android:text="@string/show_last_update_time" android:text="@string/show_last_update_time"
tools:ignore="TouchTargetSizeCheck" /> tools:ignore="TouchTargetSizeCheck" />
@@ -32,7 +38,6 @@
android:id="@+id/sw_show_wait_up_books" android:id="@+id/sw_show_wait_up_books"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="8dp"
android:text="@string/show_wait_up_count" android:text="@string/show_wait_up_count"
tools:ignore="TouchTargetSizeCheck" /> tools:ignore="TouchTargetSizeCheck" />
@@ -40,31 +45,35 @@
android:id="@+id/sw_show_bookshelf_fast_scroller" android:id="@+id/sw_show_bookshelf_fast_scroller"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="8dp"
android:text="@string/show_bookshelf_fast_scroller" android:text="@string/show_bookshelf_fast_scroller"
tools:ignore="TouchTargetSizeCheck" /> tools:ignore="TouchTargetSizeCheck" />
<LinearLayout
android:id="@+id/ll_group_style" <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:paddingTop="8dp"
android:text="@string/group_style"
android:textSize="14sp"
android:textStyle="bold" />
<TextView <com.google.android.material.chip.ChipGroup
android:layout_width="0dp" android:id="@+id/chip_group_style"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:layout_weight="1" android:layout_height="wrap_content"
android:paddingHorizontal="6dp" android:checkableBehavior="single"
android:paddingVertical="16dp" android:paddingBottom="8dp"
android:text="@string/group_style" /> app:singleSelection="true"
app:selectionRequired="true">
</com.google.android.material.chip.ChipGroup>
<Spinner <TextView
android:id="@+id/sp_group_style" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:text="排列视图"
android:entries="@array/group_style" android:textSize="14sp"
tools:ignore="TouchTargetSizeCheck" /> android:textStyle="bold"
</LinearLayout> android:paddingTop="8dp" />
<com.google.android.material.chip.ChipGroup <com.google.android.material.chip.ChipGroup
android:id="@+id/chip_group_layout" android:id="@+id/chip_group_layout"
@@ -72,8 +81,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:singleSelection="true" app:singleSelection="true"
app:selectionRequired="true" app:selectionRequired="true"
android:paddingVertical="8dp" android:paddingBottom="8dp">
android:paddingHorizontal="4dp">
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/chip_list" android:id="@+id/chip_list"
@@ -90,95 +98,42 @@
android:text="网格" /> android:text="网格" />
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>
<LinearLayout <TextView
android:id="@+id/ll_grid_slider" android:id="@+id/slider_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:text="每行列数"
android:visibility="visible"> android:textSize="14sp"
android:textStyle="bold"
android:paddingTop="8dp" />
<TextView <com.google.android.material.slider.Slider
android:layout_width="wrap_content" android:id="@+id/slider_grid_count"
android:layout_height="wrap_content"
android:text="每行列数:"
android:textSize="14sp"
android:paddingVertical="8dp"
android:paddingHorizontal="4dp"/>
<com.google.android.material.slider.Slider
android:id="@+id/slider_grid_count"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="8dp"
android:valueFrom="1"
android:valueTo="9"
android:stepSize="1"
android:value="3" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:baselineAligned="false" android:paddingVertical="8dp"
android:orientation="horizontal"> android:valueFrom="1"
android:valueTo="9"
android:stepSize="1"
android:value="3" />
<LinearLayout <TextView
android:id="@+id/ll_sort" android:layout_width="match_parent"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:paddingTop="8dp"
android:layout_weight="1" android:text="@string/sort"
android:orientation="vertical"> android:textSize="14sp"
android:textStyle="bold" />
<TextView <com.google.android.material.chip.ChipGroup
android:layout_width="match_parent" android:id="@+id/chip_group_sort"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:padding="6dp" android:layout_height="wrap_content"
android:text="@string/sort" app:singleSelection="true"
android:textSize="16sp" /> app:selectionRequired="true"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:orientation="horizontal" />
<RadioGroup
android:id="@+id/rg_sort"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bookshelf_px_0"
tools:ignore="TouchTargetSizeCheck" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bookshelf_px_1"
tools:ignore="TouchTargetSizeCheck" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bookshelf_px_2"
tools:ignore="TouchTargetSizeCheck" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bookshelf_px_3"
tools:ignore="TouchTargetSizeCheck" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bookshelf_px_4"
tools:ignore="TouchTargetSizeCheck" />
<com.google.android.material.radiobutton.MaterialRadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bookshelf_px_5"
tools:ignore="TouchTargetSizeCheck" />
</RadioGroup>
</LinearLayout>
</LinearLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
@@ -16,8 +16,8 @@
<com.google.android.material.appbar.CollapsingToolbarLayout <com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize" android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
style="?attr/collapsingToolbarLayoutLargeSize" style="?attr/collapsingToolbarLayoutMediumStyle"
app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge" app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge"
app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge" app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge"
app:contentScrim="?attr/colorSurface" app:contentScrim="?attr/colorSurface"
@@ -18,10 +18,11 @@
android:id="@+id/refresh_layout" android:id="@+id/refresh_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:paddingHorizontal="8dp"
app:layout_constraintTop_toBottomOf="@+id/title_bar" app:layout_constraintTop_toBottomOf="@+id/title_bar"
app:layout_constraintBottom_toBottomOf="parent"> app:layout_constraintBottom_toBottomOf="parent">
<io.legato.kazusa.ui.widget.recycler.RecyclerViewAtPager2 <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_bookshelf" android:id="@+id/rv_bookshelf"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/title_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:liftOnScroll="false"
android:stateListAnimator="@null">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/coll_top_bar"
android:layout_width="match_parent"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize"
style="?attr/collapsingToolbarLayoutLargeStyle"
app:collapsedTitleTextAppearance="?attr/textAppearanceTitleLarge"
app:expandedTitleTextAppearance="?attr/textAppearanceHeadlineLarge"
app:titleCollapseMode="scale"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/top_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="@string/bookshelf"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<!-- ViewPager -->
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager_bookshelf"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="8dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -2,88 +2,150 @@
<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"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cv_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:clickable="true"
android:focusable="true"
tools:ignore="UnusedAttribute">
<com.google.android.material.card.MaterialCardView
<LinearLayout android:id="@+id/cv_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:layout_marginBottom="4dp"
android:paddingTop="8dp" android:foreground="?attr/selectableItemBackground"
android:paddingLeft="8dp" android:clickable="true"
android:paddingRight="8dp" android:focusable="true"
app:strokeWidth="0dp"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:scaleType="centerCrop"
android:src="@drawable/image_cover_default"
android:transitionName="img_cover"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UnusedAttribute,ImageContrastCheck"
tools:layout_editor_absoluteX="8dp" />
<io.legato.kazusa.ui.widget.text.BadgeView
android:id="@+id/bv_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:includeFontPadding="false"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded" />
<io.legato.kazusa.ui.widget.anima.RotateLoading
android:id="@+id/rl_loading"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_gravity="right"
android:visibility="invisible"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:loading_width="2dp"
tools:ignore="RtlHardcoded" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="6dp" android:orientation="vertical">
android:ellipsize="end"
android:gravity="top|center_horizontal"
android:includeFontPadding="false"
android:lines="2"
android:text="@string/book_name"
android:textSize="12sp"
tools:ignore="RtlHardcoded,RtlSymmetry" />
</LinearLayout> <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View <io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/vw_foreground" android:id="@+id/iv_cover"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
android:background="?android:attr/selectableItemBackground" android:layout_margin="8dp"
app:layout_constraintBottom_toBottomOf="parent" android:scaleType="centerCrop"
app:layout_constraintTop_toTopOf="parent" android:src="?attr/colorSurfaceVariant"
app:layout_constraintVertical_bias="0.0" android:transitionName="img_cover"
tools:layout_editor_absoluteX="0dp" /> app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="ImageContrastCheck" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/rl_loading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="4dp"
android:layout_marginHorizontal="12dp"
android:indeterminate="true"
android:visibility="invisible"
android:layout_gravity="top"
app:layout_constraintTop_toTopOf="@id/iv_cover"
app:layout_constraintStart_toStartOf="@id/iv_cover"
app:layout_constraintEnd_toEndOf="@id/iv_cover" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/cd_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:visibility="visible"
app:cardCornerRadius="4dp"
app:strokeWidth="0dp"
app:cardBackgroundColor="?attr/colorSecondaryVariant"
app:layout_constraintTop_toTopOf="@id/iv_cover"
app:layout_constraintEnd_toEndOf="@id/iv_cover">
<TextView
android:id="@+id/tv_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/colorSurface"
android:textSize="10sp"
android:padding="4dp"
android:textStyle="bold"
android:includeFontPadding="false"
tools:text="5"
tools:ignore="SmallSp" />
</com.google.android.material.card.MaterialCardView>
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="2dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="2dp"
app:layout_constraintTop_toTopOf="@id/iv_cover"
app:layout_constraintStart_toStartOf="@id/iv_cover"
app:layout_constraintEnd_toStartOf="@id/iv_cover2"
app:layout_constraintBottom_toTopOf="@id/iv_cover3"/>
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
android:layout_marginBottom="2dp"
android:layout_marginEnd="4dp"
android:layout_marginStart="2dp"
app:layout_constraintTop_toTopOf="@id/iv_cover"
app:layout_constraintEnd_toEndOf="@id/iv_cover"
app:layout_constraintStart_toEndOf="@id/iv_cover1"
app:layout_constraintBottom_toTopOf="@id/iv_cover4"/>
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginStart="4dp"
android:layout_marginBottom="4dp"
android:layout_marginEnd="2dp"
app:layout_constraintStart_toStartOf="@id/iv_cover"
app:layout_constraintBottom_toBottomOf="@id/iv_cover"
app:layout_constraintTop_toBottomOf="@id/iv_cover1"
app:layout_constraintEnd_toStartOf="@id/iv_cover4"/>
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="4dp"
android:layout_marginStart="2dp"
app:layout_constraintBottom_toBottomOf="@id/iv_cover"
app:layout_constraintEnd_toEndOf="@id/iv_cover"
app:layout_constraintTop_toBottomOf="@id/iv_cover2"
app:layout_constraintStart_toEndOf="@id/iv_cover3"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- 书名 -->
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="4dp"
android:layout_marginHorizontal="8dp"
android:ellipsize="end"
android:gravity="left"
android:lines="2"
android:text="@string/book_name"
android:textSize="12sp"
android:textStyle="bold"
tools:ignore="RtlHardcoded" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
+180 -177
View File
@@ -1,196 +1,199 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cv_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/bg_item_focused_on_tv" android:layout_marginVertical="4dp"
android:clickable="true" app:strokeWidth="0dp">
android:focusable="true"
android:scrollbars="none"
tools:ignore="UnusedAttribute">
<io.legato.kazusa.ui.widget.image.CoverImageView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/iv_cover" android:id="@+id/cv_content"
android:layout_width="66dp" android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="12dp"
android:contentDescription="@string/img_cover"
android:scaleType="centerCrop"
android:src="@drawable/image_cover_default"
android:transitionName="img_cover"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UnusedAttribute" />
<FrameLayout
android:id="@+id/fl_has_new"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="16dp" android:clickable="true"
app:layout_constraintBottom_toBottomOf="@+id/tv_name" android:focusable="true"
app:layout_constraintRight_toRightOf="parent" android:background="?attr/selectableItemBackground"
app:layout_constraintTop_toTopOf="@+id/tv_name"> tools:ignore="UnusedAttribute">
<io.legato.kazusa.ui.widget.text.BadgeView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bv_unread" android:id="@+id/cl_cover"
android:layout_width="70dp"
android:layout_height="98dp"
android:layout_marginStart="8dp"
android:layout_marginVertical="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<!-- 书封面 -->
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/image_cover_default"
android:transitionName="img_cover"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="ImageContrastCheck" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/rl_loading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="4dp"
android:layout_marginHorizontal="6dp"
android:indeterminate="true"
android:visibility="invisible"
android:layout_gravity="top"
app:layout_constraintTop_toTopOf="@id/iv_cover"
app:layout_constraintStart_toStartOf="@id/iv_cover"
app:layout_constraintEnd_toEndOf="@id/iv_cover" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/cd_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:visibility="visible"
app:cardCornerRadius="4dp"
app:strokeWidth="0dp"
app:cardBackgroundColor="?attr/colorSecondaryVariant"
app:layout_constraintTop_toTopOf="@id/iv_cover"
app:layout_constraintEnd_toEndOf="@id/iv_cover">
<TextView
android:id="@+id/tv_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/colorSurface"
android:textSize="10sp"
android:padding="4dp"
android:textStyle="bold"
android:includeFontPadding="false"
tools:text="5"
tools:ignore="SmallSp" />
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:scrollbars="none"
android:singleLine="true"
android:layout_marginTop="4dp"
android:layout_marginHorizontal="8dp"
android:text="@string/book_name"
style="@style/ChapterNameText"
tools:ignore="RtlHardcoded,RtlSymmetry"
app:layout_constraintStart_toEndOf="@+id/cl_cover"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/cl_cover" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_author"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginTop="2dp"
android:contentDescription="@string/author"
android:scrollbars="none"
android:src="@drawable/ic_author"
tools:ignore="RtlHardcoded,RtlSymmetry"
app:layout_constraintStart_toStartOf="@+id/tv_name"
app:layout_constraintTop_toBottomOf="@+id/tv_name"/>
<TextView
android:id="@+id/tv_author"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="right" android:layout_marginStart="4dp"
android:layout_margin="5dp" android:maxLines="1"
android:includeFontPadding="false"
android:scrollbars="none" android:scrollbars="none"
tools:ignore="RtlHardcoded" /> android:singleLine="true"
android:text="@string/author"
android:textSize="13sp"
tools:ignore="RtlSymmetry,TextContrastCheck"
app:layout_constraintStart_toEndOf="@+id/iv_author"
app:layout_constraintBottom_toTopOf="@+id/iv_author"
app:layout_constraintTop_toBottomOf="@+id/iv_author" />
<io.legato.kazusa.ui.widget.anima.RotateLoading <TextView
android:id="@+id/rl_loading" android:id="@+id/tv_last_update_time"
android:layout_width="26dp" android:layout_width="wrap_content"
android:layout_height="26dp" android:layout_height="match_parent"
android:layout_gravity="right" android:layout_marginEnd="8dp"
android:visibility="invisible" android:maxLines="1"
app:loading_width="2dp" android:scrollbars="none"
tools:ignore="RtlHardcoded" /> android:singleLine="true"
</FrameLayout> android:text="123"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="@+id/tv_author"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_author" />
<TextView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/tv_name" android:id="@+id/iv_read"
android:layout_width="0dp" android:layout_width="18dp"
android:layout_height="wrap_content" android:layout_height="18dp"
android:layout_marginLeft="10dp" android:layout_marginTop="4dp"
android:layout_marginTop="12dp" android:contentDescription="@string/read_dur_progress"
android:includeFontPadding="false" android:scrollbars="none"
android:paddingLeft="2dp" android:src="@drawable/ic_history"
android:paddingBottom="4dp" tools:ignore="RtlHardcoded,RtlSymmetry"
android:scrollbars="none" app:layout_constraintStart_toStartOf="@+id/tv_name"
android:singleLine="true" app:layout_constraintTop_toBottomOf="@id/tv_author" />
android:text="@string/book_name"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/tv_author"
app:layout_constraintLeft_toRightOf="@+id/iv_cover"
app:layout_constraintRight_toLeftOf="@id/fl_has_new"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<androidx.appcompat.widget.AppCompatImageView <TextView
android:id="@+id/iv_author" android:id="@+id/tv_read"
android:layout_width="@dimen/desc_icon_size" android:layout_width="0dp"
android:layout_height="@dimen/desc_icon_size" android:layout_height="wrap_content"
android:contentDescription="@string/author" android:layout_marginStart="4dp"
android:paddingStart="2dp" android:layout_marginEnd="8dp"
android:paddingEnd="2dp" android:layout_weight="1"
android:scrollbars="none" android:scrollbars="none"
android:src="@drawable/ic_author" android:singleLine="true"
app:layout_constraintBottom_toBottomOf="@+id/tv_author" android:text="@string/read_dur_progress"
app:layout_constraintLeft_toLeftOf="@+id/tv_name" android:textSize="13sp"
app:layout_constraintTop_toTopOf="@+id/tv_author" tools:ignore="TextContrastCheck"
tools:ignore="RtlHardcoded,RtlSymmetry" /> app:layout_constraintBottom_toTopOf="@id/iv_read"
app:layout_constraintStart_toEndOf="@+id/iv_read"
app:layout_constraintTop_toBottomOf="@+id/iv_read"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/tv_author" android:id="@+id/iv_last"
android:layout_width="0dp" android:layout_width="18dp"
android:layout_height="wrap_content" android:layout_height="18dp"
android:includeFontPadding="false" android:layout_marginTop="4dp"
android:maxLines="1" android:contentDescription="@string/lasted_show"
android:paddingEnd="6dp" android:scrollbars="none"
android:scrollbars="none" android:src="@drawable/ic_book_last"
android:singleLine="true" tools:ignore="RtlHardcoded,RtlSymmetry"
android:text="@string/author" app:layout_constraintStart_toStartOf="@+id/tv_name"
android:textSize="13sp" app:layout_constraintTop_toBottomOf="@id/iv_read" />
app:layout_constraintBottom_toTopOf="@+id/tv_read"
app:layout_constraintLeft_toRightOf="@+id/iv_author"
app:layout_constraintRight_toLeftOf="@id/tv_last_update_time"
app:layout_constraintTop_toBottomOf="@+id/tv_name"
tools:ignore="RtlSymmetry,TextContrastCheck" />
<TextView <TextView
android:id="@+id/tv_last_update_time" android:id="@+id/tv_last"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:includeFontPadding="false" android:layout_marginStart="4dp"
android:maxLines="1" android:layout_marginEnd="8dp"
android:paddingEnd="6dp" android:layout_weight="1"
android:scrollbars="none" android:scrollbars="none"
android:singleLine="true" android:singleLine="true"
android:text="" android:text="@string/lasted_show"
android:textSize="13sp" android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@+id/tv_read" tools:ignore="TextContrastCheck"
app:layout_constraintHorizontal_bias="0.0" app:layout_constraintBottom_toTopOf="@id/iv_last"
app:layout_constraintLeft_toRightOf="@+id/tv_author" app:layout_constraintStart_toEndOf="@+id/iv_last"
app:layout_constraintRight_toRightOf="@id/fl_has_new" app:layout_constraintTop_toBottomOf="@+id/iv_last"
app:layout_constraintTop_toBottomOf="@+id/tv_name" app:layout_constraintEnd_toEndOf="parent"/>
tools:ignore="RtlSymmetry,TextContrastCheck" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_read"
android:layout_width="@dimen/desc_icon_size"
android:layout_height="@dimen/desc_icon_size"
android:contentDescription="@string/read_dur_progress"
android:paddingStart="2dp"
android:paddingEnd="2dp"
android:scrollbars="none"
android:src="@drawable/ic_history"
app:layout_constraintBottom_toBottomOf="@+id/tv_read"
app:layout_constraintLeft_toLeftOf="@+id/tv_name"
app:layout_constraintTop_toTopOf="@+id/tv_read"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView </androidx.constraintlayout.widget.ConstraintLayout>
android:id="@+id/tv_read"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/read_dur_progress"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@id/tv_last"
app:layout_constraintLeft_toRightOf="@+id/iv_read"
app:layout_constraintRight_toRightOf="@+id/fl_has_new"
app:layout_constraintTop_toBottomOf="@+id/tv_author"
tools:ignore="TextContrastCheck" />
<androidx.appcompat.widget.AppCompatImageView </com.google.android.material.card.MaterialCardView>
android:id="@+id/iv_last"
android:layout_width="@dimen/desc_icon_size"
android:layout_height="@dimen/desc_icon_size"
android:contentDescription="@string/lasted_show"
android:paddingStart="2dp"
android:paddingEnd="2dp"
android:scrollbars="none"
android:src="@drawable/ic_book_last"
app:layout_constraintBottom_toBottomOf="@+id/tv_last"
app:layout_constraintLeft_toLeftOf="@+id/tv_name"
app:layout_constraintTop_toTopOf="@+id/tv_last"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_last"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/lasted_show"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/iv_last"
app:layout_constraintRight_toRightOf="@id/fl_has_new"
app:layout_constraintTop_toBottomOf="@+id/tv_read"
tools:ignore="TextContrastCheck" />
<View
android:id="@+id/vw_foreground"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="?android:attr/selectableItemBackground"
android:scrollbars="none"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:layout_editor_absoluteX="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,165 +1,152 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cv_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:layout_marginVertical="4dp"
android:focusable="true" app:strokeWidth="0dp">
tools:ignore="UnusedAttribute">
<io.legato.kazusa.ui.widget.image.CoverImageView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/iv_cover" android:id="@+id/cv_content"
android:layout_width="66dp"
android:layout_height="90dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="12dp"
android:contentDescription="@string/img_cover"
android:scaleType="centerCrop"
android:src="@drawable/image_cover_default"
android:transitionName="img_cover"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UnusedAttribute" />
<FrameLayout
android:id="@+id/fl_has_new"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/iv_cover">
<io.legato.kazusa.ui.widget.text.BadgeView
android:id="@+id/bv_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_margin="5dp"
android:includeFontPadding="false"
tools:ignore="RtlHardcoded" />
<io.legato.kazusa.ui.widget.anima.RotateLoading
android:id="@+id/rl_loading"
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_gravity="right"
android:visibility="invisible"
app:loading_width="2dp"
tools:ignore="RtlHardcoded" />
</FrameLayout>
<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="12dp"
android:includeFontPadding="false"
android:paddingBottom="4dp"
android:paddingLeft="2dp"
android:singleLine="true"
android:text="@string/book_name"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/tv_author"
app:layout_constraintLeft_toRightOf="@+id/iv_cover"
app:layout_constraintRight_toLeftOf="@id/fl_has_new"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_author"
android:layout_width="@dimen/desc_icon_size"
android:layout_height="@dimen/desc_icon_size"
android:contentDescription="@string/author"
android:paddingStart="2dp"
android:paddingEnd="2dp"
android:src="@drawable/ic_author"
app:layout_constraintBottom_toBottomOf="@+id/tv_author"
app:layout_constraintLeft_toLeftOf="@+id/tv_name"
app:layout_constraintTop_toTopOf="@+id/tv_author"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_author"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:maxLines="1"
android:paddingEnd="6dp"
android:text="@string/author"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@+id/tv_read"
app:layout_constraintLeft_toRightOf="@+id/iv_author"
app:layout_constraintRight_toRightOf="@id/fl_has_new"
app:layout_constraintTop_toBottomOf="@+id/tv_name"
tools:ignore="RtlSymmetry,TextContrastCheck" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_read"
android:layout_width="@dimen/desc_icon_size"
android:layout_height="@dimen/desc_icon_size"
android:contentDescription="@string/read_dur_progress"
android:paddingStart="2dp"
android:paddingEnd="2dp"
android:src="@drawable/ic_history"
app:layout_constraintBottom_toBottomOf="@+id/tv_read"
app:layout_constraintLeft_toLeftOf="@+id/tv_name"
app:layout_constraintTop_toTopOf="@+id/tv_read"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_read"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:singleLine="true"
android:text="@string/read_dur_progress"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@id/tv_last"
app:layout_constraintLeft_toRightOf="@+id/iv_read"
app:layout_constraintRight_toRightOf="@+id/fl_has_new"
app:layout_constraintTop_toBottomOf="@+id/tv_author"
tools:ignore="TextContrastCheck" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_last"
android:layout_width="@dimen/desc_icon_size"
android:layout_height="@dimen/desc_icon_size"
android:contentDescription="@string/lasted_show"
android:paddingStart="2dp"
android:paddingEnd="2dp"
android:src="@drawable/ic_book_last"
app:layout_constraintBottom_toBottomOf="@+id/tv_last"
app:layout_constraintLeft_toLeftOf="@+id/tv_name"
app:layout_constraintTop_toTopOf="@+id/tv_last"
tools:ignore="RtlHardcoded,RtlSymmetry" />
<TextView
android:id="@+id/tv_last"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:singleLine="true"
android:text="@string/lasted_show"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/iv_last"
app:layout_constraintRight_toRightOf="@id/fl_has_new"
app:layout_constraintTop_toBottomOf="@+id/tv_read"
tools:ignore="TextContrastCheck" />
<View
android:id="@+id/vw_foreground"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground" android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent" android:focusable="true"
app:layout_constraintTop_toTopOf="parent" android:background="?attr/selectableItemBackground"
app:layout_constraintVertical_bias="0.0" tools:ignore="UnusedAttribute">
tools:layout_editor_absoluteX="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout> <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_cover"
android:layout_width="70dp"
android:layout_height="98dp"
android:layout_marginStart="8dp"
android:layout_marginVertical="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<!-- 书封面 -->
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="?attr/colorSurfaceVariant"
android:transitionName="img_cover"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="ImageContrastCheck" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/rl_loading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="4dp"
android:layout_marginHorizontal="6dp"
android:indeterminate="true"
android:visibility="invisible"
android:layout_gravity="top"
app:layout_constraintTop_toTopOf="@id/iv_cover"
app:layout_constraintStart_toStartOf="@id/iv_cover"
app:layout_constraintEnd_toEndOf="@id/iv_cover" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/cd_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:visibility="visible"
app:cardCornerRadius="4dp"
app:strokeWidth="0dp"
app:cardBackgroundColor="?attr/colorSecondaryVariant"
app:layout_constraintTop_toTopOf="@id/iv_cover"
app:layout_constraintEnd_toEndOf="@id/iv_cover">
<TextView
android:id="@+id/tv_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/colorSurface"
android:textSize="10sp"
android:padding="4dp"
android:textStyle="bold"
android:includeFontPadding="false"
tools:text="5"
tools:ignore="SmallSp" />
</com.google.android.material.card.MaterialCardView>
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="2dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="2dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/iv_cover2"
app:layout_constraintBottom_toTopOf="@id/iv_cover3"/>
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
android:layout_marginBottom="2dp"
android:layout_marginEnd="4dp"
android:layout_marginStart="2dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_cover1"
app:layout_constraintBottom_toTopOf="@id/iv_cover4"/>
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginStart="4dp"
android:layout_marginBottom="4dp"
android:layout_marginEnd="2dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_cover1"
app:layout_constraintEnd_toStartOf="@id/iv_cover4"/>
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="4dp"
android:layout_marginStart="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_cover2"
app:layout_constraintStart_toEndOf="@id/iv_cover3"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:scrollbars="none"
android:singleLine="true"
android:layout_marginHorizontal="8dp"
android:text="@string/book_name"
android:textSize="18sp"
android:textStyle="bold"
tools:ignore="RtlHardcoded,RtlSymmetry"
app:layout_constraintStart_toEndOf="@+id/cl_cover"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/cl_cover"
app:layout_constraintBottom_toBottomOf="@id/cl_cover"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
+1 -1
View File
@@ -39,7 +39,7 @@
<TextView <TextView
android:id="@+id/preference_desc" android:id="@+id/preference_desc"
android:textSize="12sp" android:textSize="13sp"
android:text="@string/default1" android:text="@string/default1"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
+11
View File
@@ -10,6 +10,7 @@
<string-array name="group_style"> <string-array name="group_style">
<item>标签</item> <item>标签</item>
<item>文件夹</item> <item>文件夹</item>
<item>隐藏标签</item>
</string-array> </string-array>
<string-array name="text_suffix"> <string-array name="text_suffix">
@@ -113,4 +114,14 @@
<item>自定义</item> <item>自定义</item>
</string-array> </string-array>
<string-array name="bookshelf_px_array">
<item>@string/bookshelf_px_0</item>
<item>@string/bookshelf_px_1</item>
<item>@string/bookshelf_px_2</item>
<item>@string/bookshelf_px_3</item>
<item>@string/bookshelf_px_4</item>
<item>@string/bookshelf_px_5</item>
</string-array>
</resources> </resources>
+30 -30
View File
@@ -2,7 +2,7 @@
<!--App--> <!--App-->
<string name="app_name">阅读</string> <string name="app_name">阅读</string>
<string name="app_name_a">阅读·A</string> <string name="app_name_a">阅读·A</string>
<string name="receiving_shared_label">阅读·搜索</string> <string name="receiving_shared_label">阅读 · 搜索</string>
<string name="tip_perm_request_storage">阅读需要访问存储卡权限,请前往“设置”—“应用权限”,打开所需权限</string> <string name="tip_perm_request_storage">阅读需要访问存储卡权限,请前往“设置”—“应用权限”,打开所需权限</string>
<!--Other--> <!--Other-->
@@ -42,7 +42,7 @@
<string name="replace_purify_desc">配置替换净化规则</string> <string name="replace_purify_desc">配置替换净化规则</string>
<string name="not_available">暂无</string> <string name="not_available">暂无</string>
<string name="enable">启用</string> <string name="enable">启用</string>
<string name="replace_purify_search">替换净化-搜索</string> <string name="replace_purify_search">替换净化 - 搜索</string>
<string name="bookshelf">书架</string> <string name="bookshelf">书架</string>
<string name="favorites">收藏夹</string> <string name="favorites">收藏夹</string>
<string name="favorite">收藏</string> <string name="favorite">收藏</string>
@@ -449,7 +449,7 @@
<string name="r_image">图片 URL 规则(ruleImage)</string> <string name="r_image">图片 URL 规则(ruleImage)</string>
<string name="r_content">内容规则(ruleContent)</string> <string name="r_content">内容规则(ruleContent)</string>
<string name="r_style">样式(style)</string> <string name="r_style">样式(style)</string>
<string name="r_inject_js">注入Js(injectJs)</string> <string name="r_inject_js">注入Js (injectJs)</string>
<string name="r_link">链接规则(ruleLink)</string> <string name="r_link">链接规则(ruleLink)</string>
<string name="check_key_word">校验关键字(checkKeyWord)</string> <string name="check_key_word">校验关键字(checkKeyWord)</string>
<string name="rule_actions">操作(actions)</string> <string name="rule_actions">操作(actions)</string>
@@ -461,7 +461,7 @@
<string name="error_get_book_info">书籍信息获取失败</string> <string name="error_get_book_info">书籍信息获取失败</string>
<string name="error_get_content">内容获取失败</string> <string name="error_get_content">内容获取失败</string>
<string name="error_get_chapter_list">目录获取失败</string> <string name="error_get_chapter_list">目录获取失败</string>
<string name="error_get_web_content">访问网站失败:%s</string> <string name="error_get_web_content">访问网站失败: %s</string>
<string name="error_read_file">文件读取失败</string> <string name="error_read_file">文件读取失败</string>
<string name="error_load_toc">加载目录失败</string> <string name="error_load_toc">加载目录失败</string>
<string name="error_get_data">获取数据失败!</string> <string name="error_get_data">获取数据失败!</string>
@@ -501,10 +501,10 @@
<string name="yes">是</string> <string name="yes">是</string>
<string name="no">否</string> <string name="no">否</string>
<string name="sure">确认</string> <string name="sure">确认</string>
<string name="sure_del">是否确认删除?</string> <string name="sure_del">是否确认删除?</string>
<string name="sure_del_any">是否确认删除 %s?</string> <string name="sure_del_any">是否确认删除 %s ?</string>
<string name="sure_del_all_book">是否删除全部书籍?</string> <string name="sure_del_all_book">是否删除全部书籍?</string>
<string name="sure_del_download_book">是否同时删除已下载的书籍目录?</string> <string name="sure_del_download_book">是否同时删除已下载的书籍目录?</string>
<string name="qr_per">扫描二维码需相机权限</string> <string name="qr_per">扫描二维码需相机权限</string>
<string name="aloud_can_not_auto_page">朗读正在运行,不能自动翻页</string> <string name="aloud_can_not_auto_page">朗读正在运行,不能自动翻页</string>
<string name="input_charset">输入编码</string> <string name="input_charset">输入编码</string>
@@ -648,7 +648,7 @@
<string name="app_folder_picker">自带文件夹选择器</string> <string name="app_folder_picker">自带文件夹选择器</string>
<string name="app_file_picker">自带文件选择器</string> <string name="app_file_picker">自带文件选择器</string>
<string name="a10_permission_toast">Android 10 以上因系统权限限制可能无法读写文件</string> <string name="a10_permission_toast">Android 10 以上因系统权限限制可能无法读写文件</string>
<string name="add_to_text_context_menu_s">长按文字在操作菜单中显示阅读·搜索</string> <string name="add_to_text_context_menu_s">长按文字在操作菜单中显示阅读 · 搜索</string>
<string name="add_to_text_context_menu_t">文字操作显示搜索</string> <string name="add_to_text_context_menu_t">文字操作显示搜索</string>
<string name="record_log">记录日志</string> <string name="record_log">记录日志</string>
<string name="log">日志</string> <string name="log">日志</string>
@@ -690,7 +690,7 @@
<string name="btn_default_s">默认</string> <string name="btn_default_s">默认</string>
<string name="main_menu">主菜单</string> <string name="main_menu">主菜单</string>
<string name="request_permission">点击授予权限</string> <string name="request_permission">点击授予权限</string>
<string name="tip_local_perm_request_storage">阅读需要访问存储卡权限,请点击下方的“授予权限”按钮,或前往“设置”—“应用权限”,打开所需权限。如果授予权限后仍然不正常,请点击右上角的“选择文件夹”,使用系统文件夹选择器。</string> <string name="tip_local_perm_request_storage">阅读需要访问存储卡权限,请点击下方的“授予权限”按钮,或前往“设置” — “应用权限”,打开所需权限。如果授予权限后仍然不正常,请点击右上角的“选择文件夹”,使用系统文件夹选择器。</string>
<string name="alouding_disable">全文朗读中不能朗读选中文字</string> <string name="alouding_disable">全文朗读中不能朗读选中文字</string>
<string name="read_body_to_lh">扩展到刘海</string> <string name="read_body_to_lh">扩展到刘海</string>
<string name="toc_updateing">更新目录中</string> <string name="toc_updateing">更新目录中</string>
@@ -756,7 +756,7 @@
<string name="clear_cache_summary">清除已下载书籍和字体缓存</string> <string name="clear_cache_summary">清除已下载书籍和字体缓存</string>
<string name="default_cover">默认封面</string> <string name="default_cover">默认封面</string>
<string name="restore_ignore">恢复忽略列表</string> <string name="restore_ignore">恢复忽略列表</string>
<string name="restore_ignore_summary">恢复时忽略一些内容不恢复,方便不同手机配置不同</string> <string name="restore_ignore_summary">选择恢复忽略内容</string>
<string name="read_config">阅读界面设置</string> <string name="read_config">阅读界面设置</string>
<string name="group_name">分组名称</string> <string name="group_name">分组名称</string>
<string name="note_content">备注内容</string> <string name="note_content">备注内容</string>
@@ -882,7 +882,7 @@
<string name="autobackup_fail">自动备份失败\n%s</string> <string name="autobackup_fail">自动备份失败\n%s</string>
<string name="end">结束</string> <string name="end">结束</string>
<string name="custom_group_summary">关闭替换分组/开启添加分组</string> <string name="custom_group_summary">关闭替换分组/开启添加分组</string>
<string name="pref_media_button_per_next">媒体按钮•上一首|下一首</string> <string name="pref_media_button_per_next">媒体按钮 • 上一首|下一首</string>
<string name="pref_media_button_per_next_summary">上一段|下一段/上一章|下一章</string> <string name="pref_media_button_per_next_summary">上一段|下一段/上一章|下一章</string>
<string name="read_aloud_by_page_summary">及时翻页,翻页时会停顿一下</string> <string name="read_aloud_by_page_summary">及时翻页,翻页时会停顿一下</string>
<string name="check_source_show_debug_message">校验显示详细信息</string> <string name="check_source_show_debug_message">校验显示详细信息</string>
@@ -932,7 +932,7 @@
<string name="show_login_header">查看登录头</string> <string name="show_login_header">查看登录头</string>
<string name="login_header">登录头</string> <string name="login_header">登录头</string>
<string name="font_scale">字体大小</string> <string name="font_scale">字体大小</string>
<string name="font_scale_summary">当前字体大小:%.1f</string> <string name="font_scale_summary">当前字体大小: %.1f</string>
<string name="tts_speech_reduce">语速减</string> <string name="tts_speech_reduce">语速减</string>
<string name="tts_speech_add">语速加</string> <string name="tts_speech_add">语速加</string>
<string name="open_sys_dir_picker_error">打开系统文件夹选择器出错,将自动打开应用文件夹选择器</string> <string name="open_sys_dir_picker_error">打开系统文件夹选择器出错,将自动打开应用文件夹选择器</string>
@@ -951,7 +951,7 @@
<string name="timeout">超时</string> <string name="timeout">超时</string>
<string name="seconds">秒</string> <string name="seconds">秒</string>
<string name="less_than">小于</string> <string name="less_than">小于</string>
<string name="check_source_config_summary">校验超时:%1$s秒\n校验项目:%2$s</string> <string name="check_source_config_summary">校验超时: %1$s秒\n校验项目: %2$s</string>
<string name="record_debug_log">记录调试日志</string> <string name="record_debug_log">记录调试日志</string>
<string name="sub_dir">子文件夹</string> <string name="sub_dir">子文件夹</string>
<string name="general">全局</string> <string name="general">全局</string>
@@ -1022,8 +1022,8 @@
<string name="remote_book">远程书籍</string> <string name="remote_book">远程书籍</string>
<string name="reading_time_sort">阅读时长排序</string> <string name="reading_time_sort">阅读时长排序</string>
<string name="last_read_time_sort">阅读时间排序</string> <string name="last_read_time_sort">阅读时间排序</string>
<string name="reading_time_tag">阅读时长:</string> <string name="reading_time_tag">阅读时长:</string>
<string name="last_read_time_tag">最后阅读时间:</string> <string name="last_read_time_tag">最后阅读时间:</string>
<string name="page_touch_slop_title">滑动翻页阈值</string> <string name="page_touch_slop_title">滑动翻页阈值</string>
<string name="page_touch_slop_dialog_title">滑动翻页阈值(0 = 系统默认值)</string> <string name="page_touch_slop_dialog_title">滑动翻页阈值(0 = 系统默认值)</string>
<string name="page_touch_slop_summary">滑动多长距离才会触发滑动翻页(系统默认值 %s px)</string> <string name="page_touch_slop_summary">滑动多长距离才会触发滑动翻页(系统默认值 %s px)</string>
@@ -1059,19 +1059,19 @@
<string name="parallel_export_book">多线程导出</string> <string name="parallel_export_book">多线程导出</string>
<string name="progress_bar_behavior">进度条行为</string> <string name="progress_bar_behavior">进度条行为</string>
<string name="source_edit_text_max_line">源编辑框最大行数</string> <string name="source_edit_text_max_line">源编辑框最大行数</string>
<string name="source_edit_max_line_summary">%s,设置行数小于屏幕可显示的最大行数可以更方便的滑动到其他的字段进行编辑</string> <string name="source_edit_max_line_summary">%s,设置行数小于屏幕可显示的最大行数可以更方便的滑动到其他的字段进行编辑</string>
<string name="restore_last_book_process">是否恢复到跳转前的阅读进度?</string> <string name="restore_last_book_process">是否恢复到跳转前的阅读进度?</string>
<string name="search_scope">搜索范围</string> <string name="search_scope">搜索范围</string>
<string name="toggle_search_scope">切换</string> <string name="toggle_search_scope">切换</string>
<string name="sure_clear_search_history">是否确认清除所有搜索历史记录</string> <string name="sure_clear_search_history">是否确认清除所有搜索历史记录</string>
<string name="no_anim_scroll_page">禁用滚动点击动画</string> <string name="no_anim_scroll_page">禁用滚动点击动画</string>
<string name="webdav_device_name">设备名称</string> <string name="webdav_device_name">设备名称</string>
<string name="web_service_wake_lock">WebService唤醒锁</string> <string name="web_service_wake_lock">WebService 唤醒锁</string>
<string name="web_service_wake_lock_summary">开启web服务的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台</string> <string name="web_service_wake_lock_summary">开启 Web 服务的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台</string>
<string name="read_aloud_wake_lock">朗读服务唤醒锁</string> <string name="read_aloud_wake_lock">朗读服务唤醒锁</string>
<string name="read_aloud_wake_lock_summary">开启朗读的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台</string> <string name="read_aloud_wake_lock_summary">开启朗读的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台</string>
<string name="audio_play_wake_lock">音频服务唤醒锁</string> <string name="audio_play_wake_lock">音频服务唤醒锁</string>
<string name="audio_play_wake_lock_summary">播放音频的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台</string> <string name="audio_play_wake_lock_summary">播放音频的时候启用唤醒锁,有些手机开启唤醒锁会被杀后台</string>
<string name="change_search_scope">切换搜索范围</string> <string name="change_search_scope">切换搜索范围</string>
<string name="copy_rule">拷贝规则</string> <string name="copy_rule">拷贝规则</string>
<string name="paste_rule">粘贴规则</string> <string name="paste_rule">粘贴规则</string>
@@ -1083,7 +1083,7 @@
<string name="same_title_removed">移除重复标题</string> <string name="same_title_removed">移除重复标题</string>
<string name="update_book_fail">更新失败</string> <string name="update_book_fail">更新失败</string>
<string name="notification_permission_rationale">阅读需要发送通知来显示朗读控制和下载进度</string> <string name="notification_permission_rationale">阅读需要发送通知来显示朗读控制和下载进度</string>
<string name="webdav_after_local_restore_confirm">webDav书源比本地新,是否恢复</string> <string name="webdav_after_local_restore_confirm">WebDav 书源比本地新,是否恢复</string>
<string name="c_whitelist">白名单(contentWhitelist)</string> <string name="c_whitelist">白名单(contentWhitelist)</string>
<string name="c_blacklist">黑名单(contentBlacklist)</string> <string name="c_blacklist">黑名单(contentBlacklist)</string>
<string name="confirm">确认</string> <string name="confirm">确认</string>
@@ -1094,13 +1094,13 @@
<string name="dict_rule">字典规则</string> <string name="dict_rule">字典规则</string>
<string name="config_dict_rule">配置字典规则</string> <string name="config_dict_rule">配置字典规则</string>
<string name="create">新建</string> <string name="create">新建</string>
<string name="url_rule">url规则(urlRule)</string> <string name="url_rule">Url规则 (urlRule)</string>
<string name="show_rule">显示规则(showRule)</string> <string name="show_rule">显示规则 (showRule)</string>
<string name="config_txt_toc_rule">配置 TXT 目录规则</string> <string name="config_txt_toc_rule">配置 TXT 目录规则</string>
<string name="import_dict_rule">导入字典规则</string> <string name="import_dict_rule">导入字典规则</string>
<string name="keep_group">保留分组</string> <string name="keep_group">保留分组</string>
<string name="server_config">服务器配置</string> <string name="server_config">服务器配置</string>
<string name="sure_upload">远程webDav链接已存在,是否继续</string> <string name="sure_upload">远程 WebDav 链接已存在,是否继续</string>
<string name="unsupport_archivefile_entry">压缩文件内没有支持的文件</string> <string name="unsupport_archivefile_entry">压缩文件内没有支持的文件</string>
<string name="no_books_dir">没有设置书籍保存位置!</string> <string name="no_books_dir">没有设置书籍保存位置!</string>
<string name="delete_alert">删除提醒</string> <string name="delete_alert">删除提醒</string>
@@ -1117,10 +1117,10 @@
<string name="select_new_source">选中新增源</string> <string name="select_new_source">选中新增源</string>
<string name="select_update_source">选中更新源</string> <string name="select_update_source">选中更新源</string>
<string name="set_local_password">设置本地密码</string> <string name="set_local_password">设置本地密码</string>
<string name="set_local_password_summary">本地密码用来对备份的敏感信息加密和解密,如需在不同设备之间同步,本地密码需一致.</string> <string name="set_local_password_summary">本地密码用来对备份的敏感信息加密和解密,如需在不同设备之间同步,本地密码需一致。</string>
<string name="only_latest_backup_t">仅保留最新备份</string> <string name="only_latest_backup_t">仅保留最新备份</string>
<string name="only_latest_backup_s">本地备份仅保留最新备份文件</string> <string name="only_latest_backup_s">本地备份仅保留最新备份文件</string>
<string name="webdav_application_authorization_error">webDav应用验证失败</string> <string name="webdav_application_authorization_error">WebDav 应用验证失败</string>
<string name="load_word_count">加载字数</string> <string name="load_word_count">加载字数</string>
<string name="replace_exclude_scope">排除范围,选填书名或者书源 URL</string> <string name="replace_exclude_scope">排除范围,选填书名或者书源 URL</string>
<string name="format_js_rule">格式化规则(formatJs)</string> <string name="format_js_rule">格式化规则(formatJs)</string>
@@ -1141,7 +1141,7 @@
<string name="bookshelf_px_5">按作者</string> <string name="bookshelf_px_5">按作者</string>
<string name="effective_replaces">起效的替换</string> <string name="effective_replaces">起效的替换</string>
<string name="export_book">导出书籍</string> <string name="export_book">导出书籍</string>
<string name="export_book_notification_content">正在导出(%1$s),还有%2$d本待导出</string> <string name="export_book_notification_content">正在导出 (%1$s) ,还有 %2$d 本待导出</string>
<string name="export_md">导出(MD)</string> <string name="export_md">导出(MD)</string>
<string name="change_source_delay">换源间隔</string> <string name="change_source_delay">换源间隔</string>
<string name="change_source_progress">结果 %1$d, 当前进度 %2$d / %3$d: %4$s</string> <string name="change_source_progress">结果 %1$d, 当前进度 %2$d / %3$d: %4$s</string>
@@ -1181,7 +1181,7 @@
<string name="beta_release_version">测试版</string> <string name="beta_release_version">测试版</string>
<string name="beta_releaseA_version">共存版</string> <string name="beta_releaseA_version">共存版</string>
<string name="stream_read_aloud_audio">流式播放音频</string> <string name="stream_read_aloud_audio">流式播放音频</string>
<string name="stream_read_aloud_audio_summary">即边下边播,网络不好时播放会断断续续,仅TTS源有效</string> <string name="stream_read_aloud_audio_summary">边下边播,网络不好时播放会断断续续,仅TTS源有效</string>
<string name="pause_read_aloud_while_phone_calls_title">来电期间暂停朗读</string> <string name="pause_read_aloud_while_phone_calls_title">来电期间暂停朗读</string>
<string name="pause_read_aloud_while_phone_calls_summary">在通话期间暂停朗读,需要读取手机状态权限</string> <string name="pause_read_aloud_while_phone_calls_summary">在通话期间暂停朗读,需要读取手机状态权限</string>
<string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string> <string name="read_aloud_read_phone_state_permission_rationale">阅读需要读取手机状态实现来电期间暂停朗读功能</string>
@@ -1197,7 +1197,7 @@
<string name="enable_auto_scroll">开启滚动</string> <string name="enable_auto_scroll">开启滚动</string>
<string name="manga_footer_config">页脚配置</string> <string name="manga_footer_config">页脚配置</string>
<string name="setting_manga_auto_page_speed">设置自动翻页速度</string> <string name="setting_manga_auto_page_speed">设置自动翻页速度</string>
<string name="book_reader_info_bar">页数. %1$d/%2$d 章节. %3$d/%4$d -> %5$s%%</string> <string name="book_reader_info_bar">页数. %1$d/%2$d 章节. %3$d/%4$d -> %5$s%%</string>
<string name="menu_download_after">下载之后章节</string> <string name="menu_download_after">下载之后章节</string>
<string name="menu_download_all">下载全部章节</string> <string name="menu_download_all">下载全部章节</string>
<string name="manga_header_chapter">《章节和文案》隐藏</string> <string name="manga_header_chapter">《章节和文案》隐藏</string>
+10
View File
@@ -15,6 +15,7 @@
<string-array name="group_style"> <string-array name="group_style">
<item>Tab</item> <item>Tab</item>
<item>Folder</item> <item>Folder</item>
<item>Hide Tab</item>
</string-array> </string-array>
<string-array name="book_sort"> <string-array name="book_sort">
@@ -195,4 +196,13 @@
<item>Customize</item> <item>Customize</item>
</string-array> </string-array>
<string-array name="bookshelf_px_array">
<item>@string/bookshelf_px_0</item>
<item>@string/bookshelf_px_1</item>
<item>@string/bookshelf_px_2</item>
<item>@string/bookshelf_px_3</item>
<item>@string/bookshelf_px_4</item>
<item>@string/bookshelf_px_5</item>
</string-array>
</resources> </resources>