ソースを参照

替换为ViewPager2

HapeLee 1 年間 前
親
コミット
8c43d4bcd1

+ 46 - 61
app/src/main/java/io/legato/kazusa/ui/main/bookshelf/style1/BookshelfFragment1.kt

@@ -2,6 +2,7 @@
 
 
 package io.legato.kazusa.ui.main.bookshelf.style1
 package io.legato.kazusa.ui.main.bookshelf.style1
 
 
+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 android.view.ViewGroup
@@ -9,7 +10,9 @@ import androidx.appcompat.widget.SearchView
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentManager
 import androidx.fragment.app.FragmentManager
 import androidx.fragment.app.FragmentStatePagerAdapter
 import androidx.fragment.app.FragmentStatePagerAdapter
+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 io.legato.kazusa.R
 import io.legato.kazusa.R
 import io.legato.kazusa.data.appDb
 import io.legato.kazusa.data.appDb
 import io.legato.kazusa.data.entities.Book
 import io.legato.kazusa.data.entities.Book
@@ -42,7 +45,6 @@ class BookshelfFragment1() : BaseBookshelfFragment(R.layout.fragment_bookshelf1)
     }
     }
 
 
     private val binding by viewBinding(FragmentBookshelf1Binding::bind)
     private val binding by viewBinding(FragmentBookshelf1Binding::bind)
-    private val adapter by lazy { TabFragmentPageAdapter(childFragmentManager) }
     private val tabLayout: TabLayout by lazy {
     private val tabLayout: TabLayout by lazy {
         binding.tabLayout.findViewById(R.id.tab_layout)
         binding.tabLayout.findViewById(R.id.tab_layout)
     }
     }
@@ -50,6 +52,8 @@ class BookshelfFragment1() : BaseBookshelfFragment(R.layout.fragment_bookshelf1)
     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
 
 
+    private lateinit var adapter: TabFragmentPageAdapter
+
     override val books: List<Book>
     override val books: List<Book>
         get() {
         get() {
             val fragment = fragmentMap[groupId]
             val fragment = fragmentMap[groupId]
@@ -63,16 +67,16 @@ class BookshelfFragment1() : BaseBookshelfFragment(R.layout.fragment_bookshelf1)
     }
     }
 
 
     private val selectedGroup: BookGroup?
     private val selectedGroup: BookGroup?
-        get() = bookGroups.getOrNull(tabLayout.selectedTabPosition)
+        get() = bookGroups.getOrNull(binding.viewPagerBookshelf.currentItem)
 
 
     private fun initView() {
     private fun initView() {
-        //binding.viewPagerBookshelf.setEdgeEffectColor(primaryColor)
-        //tabLayout.isTabIndicatorFullWidth = false
-        //tabLayout.tabMode = TabLayout.MODE_SCROLLABLE
-        // tabLayout.setSelectedTabIndicatorColor(requireContext().accentColor)
-        tabLayout.setupWithViewPager(binding.viewPagerBookshelf)
-        binding.viewPagerBookshelf.offscreenPageLimit = 1
+        adapter = TabFragmentPageAdapter(this)
         binding.viewPagerBookshelf.adapter = adapter
         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 {
     override fun onQueryTextSubmit(query: String?): Boolean {
@@ -84,6 +88,7 @@ class BookshelfFragment1() : BaseBookshelfFragment(R.layout.fragment_bookshelf1)
         return false
         return false
     }
     }
 
 
+    @SuppressLint("NotifyDataSetChanged")
     @Synchronized
     @Synchronized
     override fun upGroup(data: List<BookGroup>) {
     override fun upGroup(data: List<BookGroup>) {
         if (data.isEmpty()) {
         if (data.isEmpty()) {
@@ -93,11 +98,21 @@ class BookshelfFragment1() : BaseBookshelfFragment(R.layout.fragment_bookshelf1)
                 bookGroups.clear()
                 bookGroups.clear()
                 bookGroups.addAll(data)
                 bookGroups.addAll(data)
                 adapter.notifyDataSetChanged()
                 adapter.notifyDataSetChanged()
+                adapter = TabFragmentPageAdapter(this)
+                binding.viewPagerBookshelf.adapter = adapter
+
+                TabLayoutMediator(binding.tabLayout, binding.viewPagerBookshelf) { tab, position ->
+                    tab.text = bookGroups[position].groupName
+                }.attach()
+
                 selectLastTab()
                 selectLastTab()
-                for (i in 0 until adapter.count) {
-                    tabLayout.getTabAt(i)?.view?.setOnLongClickListener {
-                        showDialogFragment(GroupEditDialog(bookGroups[i]))
-                        true
+
+                binding.tabLayout.post {
+                    for (i in 0 until bookGroups.size) {
+                        binding.tabLayout.getTabAt(i)?.view?.setOnLongClickListener {
+                            showDialogFragment(GroupEditDialog(bookGroups[i]))
+                            true
+                        }
                     }
                     }
                 }
                 }
             }
             }
@@ -105,14 +120,24 @@ class BookshelfFragment1() : BaseBookshelfFragment(R.layout.fragment_bookshelf1)
     }
     }
 
 
     override fun upSort() {
     override fun upSort() {
-        adapter.notifyDataSetChanged()
+        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)
+                }
+            }
+        }
     }
     }
 
 
     private fun selectLastTab() {
     private fun selectLastTab() {
-        tabLayout.post {
-            tabLayout.removeOnTabSelectedListener(this)
-            tabLayout.getTabAt(AppConfig.saveTabPosition)?.select()
-            tabLayout.addOnTabSelectedListener(this)
+        binding.tabLayout.post {
+            binding.tabLayout.removeOnTabSelectedListener(this)
+            binding.tabLayout.getTabAt(AppConfig.saveTabPosition)?.select()
+            binding.tabLayout.addOnTabSelectedListener(this)
         }
         }
     }
     }
 
 
@@ -134,54 +159,14 @@ class BookshelfFragment1() : BaseBookshelfFragment(R.layout.fragment_bookshelf1)
         fragmentMap[groupId]?.gotoTop()
         fragmentMap[groupId]?.gotoTop()
     }
     }
 
 
-    private inner class TabFragmentPageAdapter(fm: FragmentManager) :
-        FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
-
-        override fun getPageTitle(position: Int): CharSequence {
-            return bookGroups[position].groupName
-        }
+    private inner class TabFragmentPageAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
+        override fun getItemCount(): Int = bookGroups.size
 
 
-        /**
-         * 确定视图位置是否更改时调用
-         * @return POSITION_NONE 已更改,刷新视图. POSITION_UNCHANGED 未更改,不刷新视图
-         */
-        override fun getItemPosition(any: Any): Int {
-            val fragment = any as BooksFragment
-            val position = fragment.position
-            val group = bookGroups.getOrNull(position)
-            if (fragment.groupId != group?.groupId) {
-                return POSITION_NONE
-            }
-            val bookSort = group.getRealBookSort()
-            fragment.setEnableRefresh(group.enableRefresh)
-            if (fragment.bookSort != bookSort) {
-                fragment.upBookSort(bookSort)
-            }
-            return POSITION_UNCHANGED
-        }
-
-        override fun getItem(position: Int): Fragment {
+        override fun createFragment(position: Int): Fragment {
             val group = bookGroups[position]
             val group = bookGroups[position]
-            return BooksFragment(position, group)
-        }
-
-        override fun getCount(): Int {
-            return bookGroups.size
-        }
-
-        override fun instantiateItem(container: ViewGroup, position: Int): Any {
-            var fragment = super.instantiateItem(container, position) as BooksFragment
-            val group = bookGroups[position]
-            /**
-             * Activity recreate 会复用之前的 Fragment,不正确的需要重新创建
-             */
-            if (fragment.isCreated && getItemPosition(fragment) == POSITION_NONE) {
-                destroyItem(container, position, fragment)
-                fragment = super.instantiateItem(container, position) as BooksFragment
-            }
+            val fragment = BooksFragment(position, group)
             fragmentMap[group.groupId] = fragment
             fragmentMap[group.groupId] = fragment
             return fragment
             return fragment
         }
         }
-
     }
     }
 }
 }

+ 32 - 34
app/src/main/java/io/legato/kazusa/ui/rss/article/RssSortActivity.kt

@@ -8,8 +8,11 @@ import android.view.MenuItem
 import android.view.ViewGroup
 import android.view.ViewGroup
 import androidx.activity.viewModels
 import androidx.activity.viewModels
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
 import androidx.fragment.app.FragmentStatePagerAdapter
 import androidx.fragment.app.FragmentStatePagerAdapter
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.lifecycleScope
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import com.google.android.material.tabs.TabLayoutMediator
 import io.legato.kazusa.R
 import io.legato.kazusa.R
 import io.legato.kazusa.base.VMBaseActivity
 import io.legato.kazusa.base.VMBaseActivity
 import io.legato.kazusa.databinding.ActivityRssArtivlesBinding
 import io.legato.kazusa.databinding.ActivityRssArtivlesBinding
@@ -29,9 +32,9 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
 
 
     override val binding by viewBinding(ActivityRssArtivlesBinding::inflate)
     override val binding by viewBinding(ActivityRssArtivlesBinding::inflate)
     override val viewModel by viewModels<RssSortViewModel>()
     override val viewModel by viewModels<RssSortViewModel>()
-    private val adapter by lazy { TabFragmentPageAdapter() }
+
+    private var adapter: TabFragmentPageAdapter? = null
     private val sortList = mutableListOf<Pair<String, String>>()
     private val sortList = mutableListOf<Pair<String, String>>()
-    private val fragmentMap = hashMapOf<String, Fragment>()
     private val editSourceResult = registerForActivityResult(
     private val editSourceResult = registerForActivityResult(
         StartActivityContract(RssSourceEditActivity::class.java)
         StartActivityContract(RssSourceEditActivity::class.java)
     ) {
     ) {
@@ -44,11 +47,11 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
 
 
     override fun onActivityCreated(savedInstanceState: Bundle?) {
     override fun onActivityCreated(savedInstanceState: Bundle?) {
         setSupportActionBar(binding.topBar)
         setSupportActionBar(binding.topBar)
-        binding.viewPager.adapter = adapter
-        binding.tabLayout.setupWithViewPager(binding.viewPager)
+
         viewModel.titleLiveData.observe(this) {
         viewModel.titleLiveData.observe(this) {
-            binding.topBar.setTitle(it)
+            binding.topBar.title = it
         }
         }
+
         viewModel.initData(intent) {
         viewModel.initData(intent) {
             upFragments()
             upFragments()
         }
         }
@@ -73,7 +76,9 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
             }
             }
 
 
             R.id.menu_refresh_sort -> viewModel.clearSortCache { upFragments() }
             R.id.menu_refresh_sort -> viewModel.clearSortCache { upFragments() }
+
             R.id.menu_set_source_variable -> setSourceVariable()
             R.id.menu_set_source_variable -> setSourceVariable()
+
             R.id.menu_edit_source -> viewModel.rssSource?.sourceUrl?.let {
             R.id.menu_edit_source -> viewModel.rssSource?.sourceUrl?.let {
                 editSourceResult.launch {
                 editSourceResult.launch {
                     putExtra("sourceUrl", it)
                     putExtra("sourceUrl", it)
@@ -100,16 +105,24 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
 
 
     private fun upFragments() {
     private fun upFragments() {
         lifecycleScope.launch {
         lifecycleScope.launch {
-            viewModel.rssSource?.sortUrls()?.let {
-                sortList.clear()
-                sortList.addAll(it)
-            }
-            if (sortList.size == 1) {
+            val sorts = viewModel.rssSource?.sortUrls().orEmpty()
+
+            sortList.clear()
+            sortList.addAll(sorts)
+
+            if (sortList.size <= 1) {
                 binding.tabLayout.gone()
                 binding.tabLayout.gone()
             } else {
             } else {
                 binding.tabLayout.visible()
                 binding.tabLayout.visible()
             }
             }
-            adapter.notifyDataSetChanged()
+
+            adapter = TabFragmentPageAdapter(this@RssSortActivity, sortList)
+            binding.viewPager.adapter = adapter
+
+            // 重新绑定 TabLayout
+            TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
+                tab.text = sortList[position].first
+            }.attach()
         }
         }
     }
     }
 
 
@@ -138,31 +151,16 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
         viewModel.rssSource?.setVariable(variable)
         viewModel.rssSource?.setVariable(variable)
     }
     }
 
 
-    private inner class TabFragmentPageAdapter :
-        FragmentStatePagerAdapter(supportFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
+    private class TabFragmentPageAdapter(
+        activity: FragmentActivity,
+        private val items: List<Pair<String, String>>
+    ) : FragmentStateAdapter(activity) {
 
 
-        override fun getItemPosition(`object`: Any): Int {
-            return POSITION_NONE
-        }
+        override fun getItemCount(): Int = items.size
 
 
-        override fun getPageTitle(position: Int): CharSequence {
-            return sortList[position].first
-        }
-
-        override fun getItem(position: Int): Fragment {
-            val sort = sortList[position]
+        override fun createFragment(position: Int): Fragment {
+            val sort = items[position]
             return RssArticlesFragment(sort.first, sort.second)
             return RssArticlesFragment(sort.first, sort.second)
         }
         }
-
-        override fun getCount(): Int {
-            return sortList.size
-        }
-
-        override fun instantiateItem(container: ViewGroup, position: Int): Any {
-            val fragment = super.instantiateItem(container, position) as Fragment
-            fragmentMap[sortList[position].first] = fragment
-            return fragment
-        }
     }
     }
-
-}
+}

+ 1 - 1
app/src/main/res/layout/activity_rss_artivles.xml

@@ -43,7 +43,7 @@
 
 
     </com.google.android.material.appbar.AppBarLayout>
     </com.google.android.material.appbar.AppBarLayout>
 
 
-    <androidx.viewpager.widget.ViewPager
+    <androidx.viewpager2.widget.ViewPager2
         android:id="@+id/view_pager"
         android:id="@+id/view_pager"
         android:layout_width="match_parent"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_height="match_parent"

+ 1 - 1
app/src/main/res/layout/fragment_bookshelf1.xml

@@ -43,7 +43,7 @@
     </com.google.android.material.appbar.AppBarLayout>
     </com.google.android.material.appbar.AppBarLayout>
 
 
     <!-- ViewPager -->
     <!-- ViewPager -->
-    <androidx.viewpager.widget.ViewPager
+    <androidx.viewpager2.widget.ViewPager2
         android:id="@+id/view_pager_bookshelf"
         android:id="@+id/view_pager_bookshelf"
         android:layout_width="match_parent"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_height="match_parent"