一个新的书架样式 #285

This commit is contained in:
HapeLee
2025-11-11 22:37:35 +08:00
parent 2c7aa63f58
commit d5944be109
7 changed files with 220 additions and 5 deletions
@@ -50,6 +50,7 @@ import io.legado.app.ui.main.bookshelf.BaseBookshelfFragment
import io.legado.app.ui.main.bookshelf.books.BookshelfFragment1
import io.legado.app.ui.main.bookshelf.books.BookshelfFragment2
import io.legado.app.ui.main.bookshelf.books.BookshelfFragment3
import io.legado.app.ui.main.bookshelf.books.BookshelfFragment4
import io.legado.app.ui.main.explore.ExploreFragment
import io.legado.app.ui.main.my.MyFragment
import io.legado.app.ui.main.rss.RssFragment
@@ -86,6 +87,7 @@ open class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
private val idBookshelf1 = 11
private val idBookshelf2 = 12
private val idBookshelf3 = 13
private val idBookshelf4 = 14
private val idExplore = 1
private val idRss = 2
private val idMy = 3
@@ -508,6 +510,7 @@ open class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
0 -> idBookshelf1
1 -> idBookshelf2
2 -> idBookshelf3
3 -> idBookshelf4
else -> idBookshelf1
}
}
@@ -543,6 +546,7 @@ open class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
idBookshelf1 -> BookshelfFragment1(position)
idBookshelf2 -> BookshelfFragment2(position)
idBookshelf3 -> BookshelfFragment3(position)
idBookshelf4 -> BookshelfFragment4(position)
idExplore -> ExploreFragment(position)
idRss -> RssFragment(position)
else -> MyFragment(position)
@@ -0,0 +1,164 @@
@file:Suppress("DEPRECATION")
package io.legado.app.ui.main.bookshelf.books
import android.annotation.SuppressLint
import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import io.legado.app.R
import io.legado.app.data.appDb
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookGroup
import io.legado.app.databinding.FragmentBookshelf1Binding
import io.legado.app.databinding.FragmentBookshelf4Binding
import io.legado.app.help.config.AppConfig
import io.legado.app.ui.book.group.GroupEditDialog
import io.legado.app.ui.book.search.SearchActivity
import io.legado.app.ui.main.bookshelf.BaseBookshelfFragment
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlin.collections.set
/**
* 书架界面
*/
class BookshelfFragment4() : BaseBookshelfFragment(R.layout.fragment_bookshelf4),
TabLayout.OnTabSelectedListener,
SearchView.OnQueryTextListener {
constructor(position: Int) : this() {
val bundle = Bundle()
bundle.putInt("position", position)
arguments = bundle
}
private val binding by viewBinding(FragmentBookshelf4Binding::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)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S)
binding.titleBar.fitsSystemWindows = true
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
TabLayoutMediator(binding.tabLayout, binding.viewPagerBookshelf) { tab, position ->
tab.text = bookGroups[position].groupName
}.attach()
}
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
TabLayoutMediator(binding.tabLayout, binding.viewPagerBookshelf) { tab, position ->
tab.text = bookGroups[position].groupName
}.attach()
selectLastTab()
binding.tabLayout.post {
for (i in 0 until bookGroups.size) {
binding.tabLayout.getTabAt(i)?.view?.setOnLongClickListener {
showDialogFragment(GroupEditDialog(bookGroups[i]))
true
}
}
}
}
}
}
override fun upSort() {
childFragmentManager.fragments.forEach {
if (it is BooksFragment) {
val position = it.position
val group = bookGroups.getOrNull(position) ?: return@forEach
it.setEnableRefresh(group.enableRefresh)
it.upBookSort(group.getRealBookSort())
}
}
}
private fun selectLastTab() {
binding.tabLayout.post {
binding.tabLayout.removeOnTabSelectedListener(this)
binding.tabLayout.getTabAt(AppConfig.saveTabPosition)?.select()
binding.tabLayout.addOnTabSelectedListener(this)
}
}
override fun onTabReselected(tab: TabLayout.Tab) {
selectedGroup?.let { group ->
fragmentMap[group.groupId]?.let {
toastOnUi("${group.groupName}(${it.getBooksCount()})")
}
}
}
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
}
}
}
@@ -93,7 +93,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingVertical="8dp"
android:text="@string/group_style"
android:textSize="14sp"
android:textStyle="bold" />
@@ -103,7 +103,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkableBehavior="single"
android:paddingBottom="8dp"
app:selectionRequired="true"
app:singleSelection="true" />
@@ -111,6 +110,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingVertical="8dp"
android:text="@string/sortview"
android:textSize="14sp"
android:textStyle="bold" />
@@ -119,7 +119,6 @@
android:id="@+id/chip_group_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:chipSpacingVertical="0dp"
android:checkableBehavior="single"
app:selectionRequired="true"
app:singleSelection="true">
@@ -191,6 +190,7 @@
android:id="@+id/chipGroupOrder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="8dp"
app:selectionRequired="true"
app:singleSelection="true">
@@ -218,7 +218,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:chipSpacingVertical="0dp"
app:selectionRequired="true"
app:singleSelection="true" />
@@ -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:background="@android:color/transparent"
android:fitsSystemWindows="true"
app:liftOnScroll="false"
android:stateListAnimator="@null">
<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.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
android:background="@android:color/transparent"
style="@style/Widget.Material3.TabLayout" />
</com.google.android.material.appbar.AppBarLayout>
<io.legado.app.ui.widget.NestedScrollableHost
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager_bookshelf"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="8dp" />
</io.legado.app.ui.widget.NestedScrollableHost>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
+2 -1
View File
@@ -11,6 +11,7 @@
<item>标签</item>
<item>文件夹</item>
<item>隐藏标签</item>
<item>材料标签</item>
</string-array>
<string-array name="text_suffix">
@@ -183,7 +184,7 @@
<string-array name="title_chapter_mode">
<item>不显示标题</item>
<item>不显示</item>
<item>不显示章节</item>
<item>Disable title and chapter display</item>
</string-array>
+1
View File
@@ -16,6 +16,7 @@
<item>Tab</item>
<item>Folder</item>
<item>Hide Tab</item>
<item>Material Tab</item>
</string-array>
<string-array name="book_sort">
+1
View File
@@ -35,6 +35,7 @@
<style name="Widget.MyApp.Chip.Assist" parent="Widget.Material3.Chip.Assist">
<item name="chipBackgroundColor">@color/chip_background_selector</item>
<item name="chipStrokeColor">@color/chip_stroke_selector</item>
<item name="chipMinTouchTargetSize">0dp</item>
</style>
<style name="NoBackgroundNavi" parent="ThemeOverlay.Material3.Toolbar.CircleNavigationButton">