From 573cc15817ddaab94d3dd556ad0296f91d2e603a Mon Sep 17 00:00:00 2001 From: HapeLee <1321903405@qq.com> Date: Sat, 29 Nov 2025 13:46:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=B7=E5=90=8D=E7=9B=B8=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8=E8=B7=B3=E8=BD=AC=E5=90=8E?= =?UTF-8?q?=E4=B8=80=E5=8D=B7=20#358?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/ui/book/toc/ChapterListAdapter.kt | 134 ++++++++++-------- .../app/ui/book/toc/ChapterListFragment.kt | 13 +- .../io/legado/app/ui/book/toc/TocActivity.kt | 5 +- 3 files changed, 86 insertions(+), 66 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListAdapter.kt b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListAdapter.kt index 7b948967a..fa057a942 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListAdapter.kt @@ -191,54 +191,15 @@ class ChapterListAdapter( if (!volume.isVolume) return val all = getItems() + val volumeIndex = volume.index val startIndex = all.indexOf(volume) if (startIndex == -1) return - val currentPos = visibleItems.indexOf(volume) - if (currentPos == -1) return + val visiblePos = visibleItems.indexOf(volume) + if (visiblePos == -1) return - if (collapsedVolumes.contains(volume.index)) { - collapsedVolumes.remove(volume.index) - - val toAdd = mutableListOf() - for (i in startIndex + 1 until all.size) { - val next = all[i] - if (next.isVolume) break - toAdd.add(next) - } - - val insertPos = currentPos + 1 - visibleItems.addAll(insertPos, toAdd) - - notifyItemRangeInserted(insertPos, toAdd.size) - notifyItemChanged(currentPos) - - } else { - collapsedVolumes.add(volume.index) - val toRemove = mutableListOf() - for (i in startIndex + 1 until all.size) { - val next = all[i] - if (next.isVolume) break - toRemove.add(next) - } - if (toRemove.isNotEmpty()) { - val removeStart = currentPos + 1 - visibleItems.removeAll(toRemove) - notifyItemRangeRemoved(removeStart, toRemove.size) - notifyItemChanged(currentPos) - } - } - } - - fun expandAllVolumes() { - val all = getItems() - var offset = 0 - - collapsedVolumes.forEach { volumeIndex -> - val volume = all.firstOrNull { it.index == volumeIndex } ?: return@forEach - val startIndex = all.indexOf(volume) - val currentPos = visibleItems.indexOf(volume) - if (currentPos == -1) return@forEach + if (collapsedVolumes.contains(volumeIndex)) { + collapsedVolumes.remove(volumeIndex) val toAdd = mutableListOf() for (i in startIndex + 1 until all.size) { @@ -248,37 +209,88 @@ class ChapterListAdapter( } if (toAdd.isNotEmpty()) { - visibleItems.addAll(currentPos + 1, toAdd) - notifyItemRangeInserted(currentPos + 1, toAdd.size) - notifyItemChanged(currentPos) - offset += toAdd.size + val insertPos = visiblePos + 1 + visibleItems.addAll(insertPos, toAdd) + notifyItemRangeInserted(insertPos, toAdd.size) + } + + notifyItemChanged(visiblePos) + + } else { + collapsedVolumes.add(volumeIndex) + + val toRemove = mutableListOf() + for (i in startIndex + 1 until all.size) { + val next = all[i] + if (next.isVolume) break + toRemove.add(next) + } + + if (toRemove.isNotEmpty()) { + val removeStart = visiblePos + 1 + visibleItems.removeAll(toRemove) + notifyItemRangeRemoved(removeStart, toRemove.size) + } + + notifyItemChanged(visiblePos) + } + } + + fun expandAllVolumes() { + val all = getItems() + var insertedOffset = 0 + + val collapsedCopy = collapsedVolumes.toList() + collapsedVolumes.clear() + + for (volumeIndex in collapsedCopy) { + val volume = all.firstOrNull { it.isVolume && it.index == volumeIndex } ?: continue + val start = all.indexOf(volume) + if (start == -1) continue + + val visiblePos = visibleItems.indexOf(volume) + if (visiblePos == -1) continue + + val children = mutableListOf() + for (i in start + 1 until all.size) { + val next = all[i] + if (next.isVolume) break + children.add(next) + } + + if (children.isNotEmpty()) { + val insertPos = visiblePos + 1 + visibleItems.addAll(insertPos, children) + notifyItemRangeInserted(insertPos, children.size) + notifyItemChanged(visiblePos) + insertedOffset += children.size } } - - collapsedVolumes.clear() } fun collapseAllVolumes() { val all = getItems() - all.filter { it.isVolume }.forEach { volume -> - val startIndex = visibleItems.indexOf(volume) - if (startIndex == -1) return@forEach + for (volume in all.filter { it.isVolume }) { + val visiblePos = visibleItems.indexOf(volume) + if (visiblePos == -1) continue + + val volumeIndex = volume.index + collapsedVolumes.add(volumeIndex) val toRemove = mutableListOf() - for (i in startIndex + 1 until visibleItems.size) { + for (i in visiblePos + 1 until visibleItems.size) { val next = visibleItems[i] if (next.isVolume) break toRemove.add(next) } if (toRemove.isNotEmpty()) { + val removeStart = visiblePos + 1 visibleItems.removeAll(toRemove) - notifyItemRangeRemoved(startIndex + 1, toRemove.size) - notifyItemChanged(startIndex) + notifyItemRangeRemoved(removeStart, toRemove.size) + notifyItemChanged(visiblePos) } - - collapsedVolumes.add(volume.index) } } @@ -286,8 +298,10 @@ class ChapterListAdapter( return getItems().filter { it.isVolume }.map { it.title } } - fun getVolumeStartPosition(volumeName: String): Int { - return getItems().indexOfFirst { it.isVolume && it.title == volumeName } + fun getVolumeStartPosition(volumePosition: Int): Int { + val volumes = getItems().filter { it.isVolume } + val volume = volumes.getOrNull(volumePosition) ?: return -1 + return getItems().indexOf(volume) } fun areAllVolumesExpanded(): Boolean { diff --git a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListFragment.kt b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListFragment.kt index ebeacf25c..f02515c63 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListFragment.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListFragment.kt @@ -301,11 +301,16 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragment_chapt return adapter.getAllVolumes() } - fun scrollToVolume(volumeName: String) { - val position = adapter.getVolumeStartPosition(volumeName) + fun scrollToVolume(volumeIndex: Int) { + val volumes = getAllVolumes() + val volumeName = volumes.getOrNull(volumeIndex) ?: "未知卷" + + val position = adapter.getVolumeStartPosition(volumeIndex) if (position >= 0) { - (binding.recyclerView.layoutManager as? LinearLayoutManager)?.scrollToPositionWithOffset(position, 0) - toastOnUi("已跳转到 $volumeName") + (binding.recyclerView.layoutManager as? LinearLayoutManager) + ?.scrollToPositionWithOffset(position, 0) + + toastOnUi("已跳转到:$volumeName") } } diff --git a/app/src/main/java/io/legado/app/ui/book/toc/TocActivity.kt b/app/src/main/java/io/legado/app/ui/book/toc/TocActivity.kt index b4ab5128a..848d7f60d 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/TocActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/TocActivity.kt @@ -179,8 +179,9 @@ class TocActivity : VMBaseActivity(), true } else -> { - if (item.groupId == R.id.action_jump_to_volume_section && item.itemId in volumes.indices) { - chapterFragment?.scrollToVolume(volumes[item.itemId]) + if (item.groupId == R.id.action_jump_to_volume_section) { + val index = item.itemId + chapterFragment?.scrollToVolume(index) true } else false }