本地书籍

This commit is contained in:
HapeLee
2025-11-16 13:39:38 +08:00
parent fdc86d7183
commit 5362d4f47f
3 changed files with 98 additions and 88 deletions
@@ -14,6 +14,7 @@ import android.transition.TransitionManager
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toDrawable
import androidx.core.view.isVisible
import androidx.fragment.app.activityViewModels
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.lifecycle.lifecycleScope
@@ -58,6 +59,7 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
private val mLayoutManager by lazy { UpLinearLayoutManager(requireContext()) }
private val adapter by lazy { ChapterListAdapter(requireContext(), this) }
private var durChapterIndex = 0
private var swipeHelper: ItemTouchHelper? = null
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) = binding.run {
viewModel.chapterListCallBack = this@ChapterListFragment
@@ -65,98 +67,12 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
initView()
viewModel.bookData.observe(this@ChapterListFragment) {
initBook(it)
initSwipeIfNeed(it.isLocal)
}
}
private fun initRecyclerView() {
val swipeCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean = false
override fun getSwipeThreshold(viewHolder: RecyclerView.ViewHolder): Float = 0.3f
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.bindingAdapterPosition
val chapter = adapter.getItem(position) ?: return
val book = book ?: return
toastOnUi("开始下载: ${adapter.getItem(position)?.title}")
CacheBook.start(requireContext(), book, listOf(chapter.index))
VibrationUtils.vibratePattern(requireContext(), longArrayOf(0, 50, 30, 50), -1)
adapter.notifyItemChanged(position)
}
override fun onChildDraw(
c: Canvas,
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
dX: Float,
dY: Float,
actionState: Int,
isCurrentlyActive: Boolean
) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE && dX > 0) {
val itemView = viewHolder.itemView
val interpolator = FastOutSlowInInterpolator()
val dampedDx =
interpolator.getInterpolation(min(1f, dX / itemView.width)) * itemView.width
// 背景
val background =
requireContext().themeColor(com.google.android.material.R.attr.colorSecondary)
.toDrawable()
background.setBounds(
itemView.left,
itemView.top,
itemView.left + dampedDx.toInt(),
itemView.bottom
)
background.draw(c)
// 图标
val icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_download)!!
val iconMargin = (itemView.height - icon.intrinsicHeight) / 2
val iconTop = itemView.top + iconMargin
val iconBottom = iconTop + icon.intrinsicHeight
val iconLeft = 12.dpToPx()
val iconRight = iconLeft + icon.intrinsicWidth
icon.setTint(requireContext().themeColor(com.google.android.material.R.attr.colorOnSecondary))
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
icon.draw(c)
super.onChildDraw(
c,
recyclerView,
viewHolder,
dampedDx,
dY,
actionState,
isCurrentlyActive
)
} else {
super.onChildDraw(
c,
recyclerView,
viewHolder,
dX,
dY,
actionState,
isCurrentlyActive
)
}
}
}
val itemTouchHelper = ItemTouchHelper(swipeCallback)
itemTouchHelper.attachToRecyclerView(binding.recyclerView)
binding.recyclerView.layoutManager = mLayoutManager
binding.recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
@@ -173,6 +89,97 @@ class ChapterListFragment : VMBaseFragment<TocViewModel>(R.layout.fragment_chapt
binding.recyclerView.adapter = adapter
}
private fun initSwipeIfNeed(isLocalBook: Boolean) {
binding.btnDownloadSelected.isEnabled = !isLocalBook
swipeHelper?.attachToRecyclerView(null)
if (!isLocalBook){
val swipeCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean = false
override fun getSwipeThreshold(viewHolder: RecyclerView.ViewHolder): Float = 0.3f
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.bindingAdapterPosition
val chapter = adapter.getItem(position) ?: return
val book = book ?: return
toastOnUi("开始下载: ${adapter.getItem(position)?.title}")
CacheBook.start(requireContext(), book, listOf(chapter.index))
VibrationUtils.vibratePattern(requireContext(), longArrayOf(0, 50, 30, 50), -1)
adapter.notifyItemChanged(position)
}
override fun onChildDraw(
c: Canvas,
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
dX: Float,
dY: Float,
actionState: Int,
isCurrentlyActive: Boolean
) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE && dX > 0) {
val itemView = viewHolder.itemView
val interpolator = FastOutSlowInInterpolator()
val dampedDx =
interpolator.getInterpolation(min(1f, dX / itemView.width)) * itemView.width
// 背景
val background =
requireContext().themeColor(com.google.android.material.R.attr.colorSecondary)
.toDrawable()
background.setBounds(
itemView.left,
itemView.top,
itemView.left + dampedDx.toInt(),
itemView.bottom
)
background.draw(c)
// 图标
val icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_download)!!
val iconMargin = (itemView.height - icon.intrinsicHeight) / 2
val iconTop = itemView.top + iconMargin
val iconBottom = iconTop + icon.intrinsicHeight
val iconLeft = 12.dpToPx()
val iconRight = iconLeft + icon.intrinsicWidth
icon.setTint(requireContext().themeColor(com.google.android.material.R.attr.colorOnSecondary))
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
icon.draw(c)
super.onChildDraw(
c,
recyclerView,
viewHolder,
dampedDx,
dY,
actionState,
isCurrentlyActive
)
} else {
super.onChildDraw(
c,
recyclerView,
viewHolder,
dX,
dY,
actionState,
isCurrentlyActive
)
}
}
}
val itemTouchHelper = ItemTouchHelper(swipeCallback)
itemTouchHelper.attachToRecyclerView(binding.recyclerView)
}
}
private fun initView() = binding.run {
llBase.applyNavigationBarPadding()
btnChapterTop.setOnClickListener {
@@ -31,6 +31,7 @@ import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.databinding.ActivityChapterListBinding
import io.legado.app.databinding.DialogDownloadChoiceBinding
import io.legado.app.help.book.isLocal
import io.legado.app.help.book.isLocalTxt
import io.legado.app.help.config.AppConfig
import io.legado.app.lib.dialogs.alert
@@ -64,6 +65,7 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
private var menu: Menu? = null
private var searchView: SearchView? = null
private val waitDialog by lazy { WaitDialog(this) }
private var isLocalBook : Boolean = false
private val exportDir = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
when (it.requestCode) {
@@ -88,6 +90,7 @@ class TocActivity : VMBaseActivity<ActivityChapterListBinding, TocViewModel>(),
viewModel.bookData.observe(this) { book ->
menu?.setGroupVisible(R.id.menu_group_text, book.isLocalTxt)
supportActionBar?.title = book.name
binding.topBar.menu.findItem(R.id.menu_download)?.isVisible = !book.isLocal
}
intent.getStringExtra("bookUrl")?.let {
viewModel.initBook(it)