增加一个新的紧凑列表布局

This commit is contained in:
HapeLee
2025-10-09 02:13:36 +08:00
parent 8a7936d6fa
commit cc4b9c31d2
14 changed files with 724 additions and 124 deletions
@@ -36,6 +36,7 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog
val isGrid = bookshelfLayout == 1
val isGridCompact = bookshelfLayout == 2
val isGridCover = bookshelfLayout == 3
val isListCompact = bookshelfLayout == 4
val columnCount = requireContext().bookshelfLayoutGrid.takeIf { it > 0 } ?: 1
@@ -76,13 +77,17 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog
swShowBookshelfFastScroller.isChecked = AppConfig.showBookshelfFastScroller
chipList.isChecked = isList
chipListCompact.isChecked = isListCompact
chipGrid.isChecked = isGrid
chipGridCompact.isChecked = isGridCompact
chipGridCover.isChecked = isGridCover
sliderText.isVisible = isGrid || isGridCompact || isGridCover
sliderGridCount.isVisible = isGrid || isGridCompact || isGridCover
val showSlider = isGrid || isGridCompact || isGridCover
sliderText.isVisible = showSlider
sliderGridCount.isVisible = showSlider
sliderGridCount.value = columnCount.toFloat()
when (AppConfig.bookshelfSortOrder) {
0 -> binding.chipGroupOrder.check(binding.chipAsc.id)
1 -> binding.chipGroupOrder.check(binding.chipDesc.id)
@@ -90,10 +95,11 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog
chipGroupLayout.setOnCheckedStateChangeListener { _, checkedIds ->
val checkedId = checkedIds.firstOrNull()
val showSlider =
checkedId == R.id.chip_grid || checkedId == R.id.chip_grid_compact || checkedId == R.id.chip_grid_cover
sliderText.isVisible = showSlider
val showSlider = checkedId == R.id.chip_grid ||
checkedId == R.id.chip_grid_compact ||
checkedId == R.id.chip_grid_cover
TransitionManager.beginDelayedTransition(root)
sliderText.isVisible = showSlider
sliderGridCount.isVisible = showSlider
}
@@ -136,6 +142,7 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog
chipGrid.isChecked -> 1
chipGridCompact.isChecked -> 2
chipGridCover.isChecked -> 3
chipListCompact.isChecked -> 4
else -> 0
}
@@ -149,7 +156,7 @@ class BookshelfConfigBottomSheet : BaseBottomSheetDialogFragment(R.layout.dialog
AppConfig.bookshelfLayoutGridPortrait = selectedColumn
}
if (newLayout == 0) {
if (newLayout == 0 || newLayout == 4) {
activityViewModel.booksGridRecycledViewPool.clear()
} else {
activityViewModel.booksListRecycledViewPool.clear()
@@ -39,6 +39,7 @@ import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BooksAdapterGrid
import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BooksAdapterGridCompact
import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BooksAdapterGridCover
import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BooksAdapterList
import io.legato.kazusa.ui.main.bookshelf.books.styleDefalut.BooksAdapterListCompact
import io.legato.kazusa.utils.bookshelfLayoutGrid
import io.legato.kazusa.utils.bookshelfLayoutMode
import io.legato.kazusa.utils.cnCompare
@@ -92,9 +93,13 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
BooksAdapterGridCompact(requireContext(), this)
}
else -> {
3 -> {
BooksAdapterGridCover(requireContext(), this)
}
else -> {
BooksAdapterListCompact(requireContext(), this, this, viewLifecycleOwner.lifecycle)
}
}
}
private var booksFlowJob: Job? = null
@@ -127,7 +132,7 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
binding.refreshLayout.isRefreshing = false
activityViewModel.upToc(booksAdapter.getItems())
}
if (bookshelfLayoutMode == 0) {
if (bookshelfLayoutMode == 0 ||bookshelfLayoutMode == 4) {
binding.rvBookshelf.layoutManager = LinearLayoutManager(context)
binding.rvBookshelf.setRecycledViewPool(activityViewModel.booksListRecycledViewPool)
} else {
@@ -232,7 +237,7 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
private fun startLastUpdateTimeJob() {
upLastUpdateTimeJob?.cancel()
if (!AppConfig.showLastUpdateTime || bookshelfLayoutMode != 0) {
if (!AppConfig.showLastUpdateTime || bookshelfLayoutMode != 0 ||bookshelfLayoutMode != 4) {
return
}
upLastUpdateTimeJob = lifecycleScope.launch {
@@ -36,6 +36,7 @@ import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BooksAdapterGrid
import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BooksAdapterGridCompact
import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BooksAdapterGridCover
import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BooksAdapterList
import io.legato.kazusa.ui.main.bookshelf.books.styleFold.BooksAdapterListCompact
import io.legato.kazusa.utils.bookshelfLayoutGrid
import io.legato.kazusa.utils.bookshelfLayoutMode
import io.legato.kazusa.utils.cnCompare
@@ -85,9 +86,13 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
BooksAdapterGridCompact(requireContext(), this)
}
else -> {
3 -> {
BooksAdapterGridCover(requireContext(), this)
}
else -> {
BooksAdapterListCompact(requireContext(), this)
}
}
}
@@ -111,7 +116,7 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
binding.refreshLayout.isRefreshing = false
activityViewModel.upToc(books)
}
if (bookshelfLayoutMode == 0) {
if (bookshelfLayoutMode == 0 || bookshelfLayoutMode == 4) {
binding.rvBookshelf.layoutManager = LinearLayoutManager(context)
} else {
binding.rvBookshelf.layoutManager = GridLayoutManager(context, bookshelfLayoutGrid)
@@ -0,0 +1,116 @@
package io.legato.kazusa.ui.main.bookshelf.books.styleDefalut
import android.content.Context
import android.os.Bundle
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import io.legato.kazusa.R
import io.legato.kazusa.base.adapter.ItemViewHolder
import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.databinding.ItemBookshelfListCompactBinding
import io.legato.kazusa.help.book.isLocal
import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.utils.toTimeAgo
import splitties.views.onLongClick
class BooksAdapterListCompact(
context: Context,
private val fragment: Fragment,
private val callBack: CallBack,
private val lifecycle: Lifecycle
) : BaseBooksAdapter<ItemBookshelfListCompactBinding>(context) {
override fun getViewBinding(parent: ViewGroup): ItemBookshelfListCompactBinding {
return ItemBookshelfListCompactBinding.inflate(inflater, parent, false)
}
override fun convert(
holder: ItemViewHolder,
binding: ItemBookshelfListCompactBinding,
item: Book,
payloads: MutableList<Any>
) = binding.run {
binding.cdCover.transitionName = "book_${item.bookUrl}"
if (payloads.isEmpty()) {
tvName.text = item.name
tvAuthor.text =
context.getString(
R.string.author_read,
item.author,
(item.totalChapterNum - item.durChapterIndex).coerceAtLeast(0)
)
tvLast.text = item.latestChapterTitle
ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin)
upRefresh(binding, item)
upLastUpdateTime(binding, item)
} else {
for (i in payloads.indices) {
val bundle = payloads[i] as Bundle
bundle.keySet().forEach {
when (it) {
"name" -> tvName.text = item.name
"author" -> tvAuthor.text = item.author
"last" -> tvLast.text = item.latestChapterTitle
"cover" -> ivCover.load(
item.getDisplayCover(),
item.name,
item.author,
false,
item.origin,
fragment,
lifecycle
)
"refresh" -> upRefresh(binding, item)
"lastUpdateTime" -> upLastUpdateTime(binding, item)
}
}
}
}
}
private fun upRefresh(binding: ItemBookshelfListCompactBinding, item: Book) {
if (!item.isLocal && callBack.isUpdate(item.bookUrl)) {
binding.tvUnread.isVisible = false
binding.rlLoading.isVisible = true
} else {
binding.rlLoading.isVisible = false
if (AppConfig.showUnread) {
//binding.tvUnread.setHighlight(item.lastCheckCount > 0)
binding.tvUnread.isVisible = true
binding.tvUnread.text = item.getUnreadChapterNum().toString()
} else {
binding.tvUnread.isVisible = false
}
}
}
private fun upLastUpdateTime(binding: ItemBookshelfListCompactBinding, 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 = ""
}
}
override fun registerListener(holder: ItemViewHolder, binding: ItemBookshelfListCompactBinding) {
holder.itemView.apply {
binding.cvContent.setOnClickListener {
getItem(holder.layoutPosition)?.let {
callBack.open(it, binding.cdCover)
}
}
binding.cvContent.onLongClick {
getItem(holder.layoutPosition)?.let {
callBack.openBookInfo(it, binding.cdCover)
}
}
}
}
}
@@ -65,9 +65,9 @@ class BooksAdapterList(context: Context, callBack: CallBack) :
tvLast.text = item.latestChapterTitle
ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin)
cdUnread.visible()
ivAuthor.visible()
ivLast.visible()
ivRead.visible()
// ivAuthor.visible()
// ivLast.visible()
// ivRead.visible()
upRefresh(this, item)
upLastUpdateTime(binding, item)
}
@@ -0,0 +1,194 @@
package io.legato.kazusa.ui.main.bookshelf.books.styleFold
import android.content.Context
import android.os.Bundle
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import io.legato.kazusa.R
import io.legato.kazusa.data.entities.Book
import io.legato.kazusa.data.entities.BookGroup
import io.legato.kazusa.databinding.ItemBookshelfListCompactBinding
import io.legato.kazusa.databinding.ItemBookshelfListCompactGroupBinding
import io.legato.kazusa.help.book.isLocal
import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.utils.gone
import io.legato.kazusa.utils.toTimeAgo
import io.legato.kazusa.utils.visible
import splitties.views.onLongClick
@Suppress("UNUSED_PARAMETER")
class BooksAdapterListCompact(context: Context, callBack: CallBack) :
BaseBooksAdapter<RecyclerView.ViewHolder>(context, callBack) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
1 -> GroupViewHolder(ItemBookshelfListCompactGroupBinding.inflate(inflater, parent, false))
else -> BookViewHolder(ItemBookshelfListCompactBinding.inflate(inflater, parent, false))
}
}
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
when (holder) {
is BookViewHolder -> (getItem(position) as? Book)?.let {
holder.registerListener(it)
holder.onBind(it, payloads)
}
is GroupViewHolder -> (getItem(position) as? BookGroup)?.let {
holder.registerListener(it)
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: ItemBookshelfListCompactBinding) :
RecyclerView.ViewHolder(binding.root) {
fun onBind(item: Book) = binding.run {
tvName.text = item.name
tvAuthor.text = item.author
tvLast.text = item.latestChapterTitle
ivCover.load(item.getDisplayCover(), item.name, item.author, false, item.origin)
cdUnread.visible()
// ivAuthor.visible()
// ivLast.visible()
// ivRead.visible()
upRefresh(this, item)
upLastUpdateTime(binding, item)
}
fun onBind(item: Book, payloads: MutableList<Any>) = binding.run {
if (payloads.isEmpty()) {
onBind(item)
} else {
for (i in payloads.indices) {
val bundle = payloads[i] as Bundle
bundle.keySet().forEach {
when (it) {
"name" -> tvName.text = item.name
"author" -> tvAuthor.text = item.author
"last" -> tvLast.text = item.latestChapterTitle
"cover" -> ivCover.load(
item.getDisplayCover(),
item.name,
item.author,
false,
item.origin
)
"refresh" -> upRefresh(this, item)
"lastUpdateTime" -> upLastUpdateTime(binding, item)
}
}
}
}
}
private fun upLastUpdateTime(binding: ItemBookshelfListCompactBinding, 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) {
binding.cvContent.setOnClickListener {
callBack.onItemClick(item, binding.cdCover)
}
binding.cvContent.onLongClick {
callBack.onItemLongClick(item, binding.cdCover)
}
}
private fun upRefresh(binding: ItemBookshelfListCompactBinding, item: Book) {
if (!item.isLocal && callBack.isUpdate(item.bookUrl)) {
binding.tvUnread.isVisible = false
binding.rlLoading.isVisible = true
} else {
binding.rlLoading.isVisible = false
if (AppConfig.showUnread) {
//binding.tvUnread.setHighlight(item.lastCheckCount > 0)
binding.tvUnread.isVisible = true
binding.tvUnread.text = item.getUnreadChapterNum().toString()
} else {
binding.tvUnread.isVisible = false
}
}
}
}
inner class GroupViewHolder(val binding: ItemBookshelfListCompactGroupBinding) :
RecyclerView.ViewHolder(binding.root) {
fun onBind(item: BookGroup) = binding.run {
tvName.text = item.groupName
loadGroupCover(item)
cdUnread.gone()
}
fun onBind(item: BookGroup, payloads: MutableList<Any>) = binding.run {
if (payloads.isEmpty()) {
onBind(item)
} else {
for (i in payloads.indices) {
val bundle = payloads[i] as Bundle
bundle.keySet().forEach {
when (it) {
"groupName" -> tvName.text = item.groupName
"cover" -> loadGroupCover(item)
}
}
}
}
}
fun registerListener(item: Any) {
binding.cvContent.setOnClickListener {
callBack.onItemClick(item, binding.ivCover)
}
binding.cvContent.onLongClick {
callBack.onItemLongClick(item, binding.ivCover)
}
}
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)
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())
}
}
}
}
@@ -111,6 +111,13 @@
android:checkable="true"
android:text="@string/list" />
<com.google.android.material.chip.Chip
android:id="@+id/chip_list_compact"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checkable="true"
android:text="@string/compact_list" />
<com.google.android.material.chip.Chip
android:id="@+id/chip_grid"
android:layout_width="wrap_content"
+83 -106
View File
@@ -4,7 +4,6 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="4dp"
app:strokeWidth="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
@@ -85,122 +84,100 @@
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/tv_name"
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:scrollbars="none"
android:singleLine="true"
android:layout_marginTop="4dp"
android:orientation="vertical"
android:layout_marginHorizontal="8dp"
android:text="@string/book_name"
style="@style/ChapterNameText"
tools:ignore="RtlHardcoded,RtlSymmetry"
app:layout_constraintStart_toEndOf="@+id/cd_cover"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/cd_cover" />
android:gravity="center_vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/cd_cover"
app:layout_constraintEnd_toEndOf="parent">
<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_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/book_name"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="RtlHardcoded,RtlSymmetry"
app:layout_constraintStart_toEndOf="@+id/cd_cover"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/cd_cover" />
<TextView
android:id="@+id/tv_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:maxLines="1"
android:scrollbars="none"
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" />
<TextView
android:id="@+id/tv_author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:maxLines="1"
android:scrollbars="none"
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" />
<TextView
android:id="@+id/tv_last_update_time"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="8dp"
android:maxLines="1"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/text"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="@+id/tv_author"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_author" />
<TextView
android:id="@+id/tv_read"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/read_dur_progress"
android:textSize="13sp"
tools:ignore="TextContrastCheck"
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"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_read"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginTop="4dp"
android:contentDescription="@string/read_dur_progress"
android:scrollbars="none"
android:src="@drawable/ic_history"
tools:ignore="RtlHardcoded,RtlSymmetry"
app:layout_constraintStart_toStartOf="@+id/tv_name"
app:layout_constraintTop_toBottomOf="@id/tv_author" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_read"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/read_dur_progress"
android:textSize="13sp"
tools:ignore="TextContrastCheck"
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
android:id="@+id/tv_last_update_time"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="4dp"
android:maxLines="1"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/text"
android:textSize="13sp"
android:textColor="?attr/colorPrimary"
app:layout_constraintBottom_toTopOf="@id/iv_last"
app:layout_constraintStart_toEndOf="@+id/iv_last"
app:layout_constraintTop_toBottomOf="@+id/iv_last" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_last"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginTop="4dp"
android:contentDescription="@string/lasted_show"
android:scrollbars="none"
android:src="@drawable/ic_book_last"
tools:ignore="RtlHardcoded,RtlSymmetry"
app:layout_constraintStart_toStartOf="@+id/tv_name"
app:layout_constraintTop_toBottomOf="@id/iv_read" />
<TextView
android:id="@+id/tv_last"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/lasted_show"
android:textSize="13sp"
tools:ignore="TextContrastCheck"
app:layout_constraintBottom_toTopOf="@id/iv_last"
app:layout_constraintStart_toEndOf="@+id/tv_last_update_time"
app:layout_constraintTop_toBottomOf="@+id/iv_last"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/tv_last"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/lasted_show"
android:textSize="13sp"
tools:ignore="TextContrastCheck"
app:layout_constraintBottom_toTopOf="@id/iv_last"
app:layout_constraintStart_toEndOf="@+id/iv_last"
app:layout_constraintTop_toBottomOf="@+id/iv_last"
app:layout_constraintEnd_toEndOf="parent"/>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<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:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:strokeWidth="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
tools:ignore="UnusedAttribute">
<com.google.android.material.card.MaterialCardView
android:id="@+id/cd_cover"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="6dp"
app:strokeWidth="0dp"
android:layout_margin="8dp"
android:transitionName="img_cover"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_cover"
android:layout_width="55dp"
android:layout_height="77dp">
<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"
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="9sp"
android:padding="3dp"
android:textStyle="bold"
android:includeFontPadding="false"
tools:text="5"
tools:ignore="SmallSp" />
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginHorizontal="8dp"
android:gravity="center_vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/cd_cover"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/book_name"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="RtlHardcoded,RtlSymmetry"
app:layout_constraintStart_toEndOf="@+id/cd_cover"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/cd_cover" />
<TextView
android:id="@+id/tv_author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:maxLines="1"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/author_read"
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" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_last_update_time"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="4dp"
android:maxLines="1"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/text"
android:textSize="13sp"
android:textColor="?attr/colorSecondary"
app:layout_constraintBottom_toTopOf="@id/iv_last"
app:layout_constraintStart_toEndOf="@+id/iv_last"
app:layout_constraintTop_toBottomOf="@+id/iv_last" />
<TextView
android:id="@+id/tv_last"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:scrollbars="none"
android:singleLine="true"
android:text="@string/lasted_show"
android:textSize="13sp"
tools:ignore="TextContrastCheck"
app:layout_constraintBottom_toTopOf="@id/iv_last"
app:layout_constraintStart_toEndOf="@+id/tv_last_update_time"
app:layout_constraintTop_toBottomOf="@+id/iv_last"
app:layout_constraintEnd_toEndOf="parent"/>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<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:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:strokeWidth="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
tools:ignore="UnusedAttribute">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_cover"
android:layout_width="55dp"
android:layout_height="77dp"
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="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<io.legato.kazusa.ui.widget.image.CoverImageView
android:id="@+id/iv_cover2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="4dp"
android:layout_marginEnd="4dp"
android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:scrollbars="none"
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>
@@ -4,7 +4,6 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="4dp"
app:strokeWidth="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
@@ -136,7 +135,6 @@
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"
@@ -37,8 +37,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingEnd="@dimen/fastscroll_scrollbar_padding_end"
android:paddingStart="@dimen/fastscroll_scrollbar_padding_start"
tools:ignore="ContentDescription"
android:src="@drawable/fastscroll_handle" />
+2
View File
@@ -1284,4 +1284,6 @@
<string name="use_animation">使用共享元素动画</string>
<string name="reduce_stutter">减少进入阅读界面时的卡顿,但加载书籍时间会延长。</string>
<string name="delay_book_load">延缓书籍加载</string>
<string name="compact_list">紧凑列表</string>
<string name="author_read">%s • %d章未读</string>
</resources>
+2
View File
@@ -1285,4 +1285,6 @@
<string name="use_animation">Use Shared Element Animation</string>
<string name="reduce_stutter">Reduces stutter when entering the reading interface, but increases book loading time.</string>
<string name="delay_book_load">Delay Book Loading</string>
<string name="compact_list">Compact List</string>
<string name="author_read">%s • %dNot read</string>
</resources>