From e4c1d3bd889d540ac641df61b9aef61b5386e655 Mon Sep 17 00:00:00 2001 From: gedoor Date: Sun, 28 Mar 2021 23:42:33 +0800 Subject: [PATCH] viewPager --- .../io/legado/app/ui/main/MainActivity.kt | 79 ++++++++------- .../ui/main/bookshelf/BookshelfFragment.kt | 98 +++++-------------- app/src/main/res/layout/activity_main.xml | 2 +- .../main/res/layout/fragment_bookshelf.xml | 2 +- 4 files changed, 69 insertions(+), 112 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt index ee817d9e1..55a1498f4 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt @@ -3,10 +3,12 @@ package io.legado.app.ui.main import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem +import android.view.ViewGroup import androidx.activity.viewModels import androidx.fragment.app.Fragment -import androidx.viewpager2.adapter.FragmentStateAdapter -import androidx.viewpager2.widget.ViewPager2 +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentStatePagerAdapter +import androidx.viewpager.widget.ViewPager import com.google.android.material.bottomnavigation.BottomNavigationView import io.legado.app.BuildConfig import io.legado.app.R @@ -34,15 +36,14 @@ import io.legado.app.utils.toastOnUi class MainActivity : VMBaseActivity(), BottomNavigationView.OnNavigationItemSelectedListener, - BottomNavigationView.OnNavigationItemReselectedListener { + BottomNavigationView.OnNavigationItemReselectedListener, + ViewPager.OnPageChangeListener by ViewPager.SimpleOnPageChangeListener() { override val viewModel: MainViewModel by viewModels() private var exitTime: Long = 0 private var bookshelfReselected: Long = 0 private var exploreReselected: Long = 0 private var pagePosition = 0 - private val fragmentMap = hashMapOf() - - val viewPager get() = binding.viewPagerMain + private val fragmentMap = hashMapOf() override fun getViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) @@ -52,21 +53,8 @@ class MainActivity : VMBaseActivity(), ATH.applyEdgeEffectColor(viewPagerMain) ATH.applyBottomNavigationColor(bottomNavigationView) viewPagerMain.offscreenPageLimit = 3 - viewPagerMain.adapter = TabFragmentPageAdapter() - viewPagerMain.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { - override fun onPageSelected(position: Int) { - viewPagerMain.isUserInputEnabled = (viewPagerMain.currentItem != 0) - pagePosition = position - when (position) { - 0, 1, 3 -> bottomNavigationView.menu.getItem(position).isChecked = true - 2 -> if (AppConfig.isShowRSS) { - bottomNavigationView.menu.getItem(position).isChecked = true - } else { - bottomNavigationView.menu.getItem(3).isChecked = true - } - } - } - }) + viewPagerMain.adapter = TabFragmentPageAdapter(supportFragmentManager) + viewPagerMain.addOnPageChangeListener(this@MainActivity) bottomNavigationView.elevation = if (AppConfig.elevation < 0) elevation else AppConfig.elevation.toFloat() bottomNavigationView.setOnNavigationItemSelectedListener(this@MainActivity) @@ -104,14 +92,14 @@ class MainActivity : VMBaseActivity(), if (System.currentTimeMillis() - bookshelfReselected > 300) { bookshelfReselected = System.currentTimeMillis() } else { - (fragmentMap[0L] as? BookshelfFragment)?.gotoTop() + (fragmentMap[0] as? BookshelfFragment)?.gotoTop() } } R.id.menu_explore -> { if (System.currentTimeMillis() - exploreReselected > 300) { exploreReselected = System.currentTimeMillis() } else { - (fragmentMap[1L] as? ExploreFragment)?.compressExplore() + (fragmentMap[1] as? ExploreFragment)?.compressExplore() } } } @@ -132,6 +120,18 @@ class MainActivity : VMBaseActivity(), } } + override fun onPageSelected(position: Int) = with(binding) { + pagePosition = position + when (position) { + 0, 1, 3 -> bottomNavigationView.menu.getItem(position).isChecked = true + 2 -> if (AppConfig.isShowRSS) { + bottomNavigationView.menu.getItem(position).isChecked = true + } else { + bottomNavigationView.menu.getItem(3).isChecked = true + } + } + } + override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean { event?.let { when (keyCode) { @@ -186,29 +186,36 @@ class MainActivity : VMBaseActivity(), } } - private inner class TabFragmentPageAdapter : - FragmentStateAdapter(this) { + private inner class TabFragmentPageAdapter(fm: FragmentManager) : + FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { - override fun getItemId(position: Int): Long { + private fun getId(position: Int): Int { return when (position) { 2 -> if (AppConfig.isShowRSS) 2 else 3 - else -> position.toLong() + else -> position } } - override fun getItemCount(): Int { - return if (AppConfig.isShowRSS) 4 else 3 + override fun getItemPosition(`object`: Any): Int { + return POSITION_NONE } - override fun createFragment(position: Int): Fragment { - val id = getItemId(position) - val fragment = when (id) { - 0L -> BookshelfFragment() - 1L -> ExploreFragment() - 2L -> RssFragment() + override fun getItem(position: Int): Fragment { + return when (getId(position)) { + 0 -> BookshelfFragment() + 1 -> ExploreFragment() + 2 -> RssFragment() else -> MyFragment() } - fragmentMap[id] = fragment + } + + override fun getCount(): Int { + return if (AppConfig.isShowRSS) 4 else 3 + } + + override fun instantiateItem(container: ViewGroup, position: Int): Any { + val fragment = super.instantiateItem(container, position) as Fragment + fragmentMap[getId(position)] = fragment return fragment } diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt index 626f227ed..4ff1e9b50 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt @@ -7,13 +7,11 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.View +import android.view.ViewGroup import androidx.appcompat.widget.SearchView import androidx.fragment.app.* import androidx.lifecycle.LiveData -import androidx.viewpager2.adapter.FragmentStateAdapter -import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.tabs.TabLayout -import com.google.android.material.tabs.TabLayoutMediator import io.legado.app.R import io.legado.app.base.VMBaseFragment import io.legado.app.constant.AppConst @@ -33,7 +31,6 @@ import io.legado.app.ui.book.local.ImportBookActivity import io.legado.app.ui.book.search.SearchActivity import io.legado.app.ui.filepicker.FilePicker import io.legado.app.ui.filepicker.FilePickerDialog -import io.legado.app.ui.main.MainActivity import io.legado.app.ui.main.MainViewModel import io.legado.app.ui.main.bookshelf.books.BooksFragment import io.legado.app.utils.* @@ -51,18 +48,12 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b private val binding by viewBinding(FragmentBookshelfBinding::bind) override val viewModel: BookshelfViewModel by viewModels() private val activityViewModel: MainViewModel by activityViewModels() + private lateinit var adapter: FragmentStatePagerAdapter private lateinit var tabLayout: TabLayout private var bookGroupLiveData: LiveData>? = null private val bookGroups = mutableListOf() private val fragmentMap = hashMapOf() - private var currentPosition = 0 //当前滑动位置 - private var oldPosition = 0 //上一个滑动位置 - private var currentState = 0 //记录当前手指按下状态 - private var scrolledPixList = mutableListOf() //记录手指滑动时的像素坐标记录 - - private val mainActivity get() = activity as MainActivity - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { tabLayout = binding.titleBar.findViewById(R.id.tab_layout) setSupportToolbar(binding.titleBar.toolbar) @@ -110,64 +101,15 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b private val selectedGroup: BookGroup get() = bookGroups[tabLayout.selectedTabPosition] - private fun initView() = with(binding) { - ATH.applyEdgeEffectColor(viewPagerBookshelf) + private fun initView() { + ATH.applyEdgeEffectColor(binding.viewPagerBookshelf) tabLayout.isTabIndicatorFullWidth = false tabLayout.tabMode = TabLayout.MODE_SCROLLABLE tabLayout.setSelectedTabIndicatorColor(requireContext().accentColor) - viewPagerBookshelf.offscreenPageLimit = 1 - viewPagerBookshelf.adapter = TabFragmentPageAdapter() - TabLayoutMediator(tabLayout, viewPagerBookshelf) { tab, i -> - tab.text = bookGroups[i].groupName - }.attach() - viewPagerBookshelf.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { - //页面滚动的位置信息回调: position 当前滚动到哪个页面,positionOffset 位置偏移百分比, positionOffsetPixels 当前所在页面偏移量 - //此回调会触发完onPageScrollStateChanged 的 state 值为1时后面才触发回调 - override fun onPageScrolled( - position: Int, - positionOffset: Float, - positionOffsetPixels: Int - ) { - currentPosition = position - if (currentState == 1) { - //手指按下滑动坐标记录 - scrolledPixList.add(positionOffsetPixels) - } - } - - - // 滚动状态改变回调,state的值分别有0,1,2 ; - // 0为ViewPager所有事件(1,2)已结束触发 - // 1为在viewPager里按下并滑动触发多次 - // 2是手指抬起触发 - override fun onPageScrollStateChanged(state: Int) { - currentState = state - if (state == 0) { - if (currentPosition == oldPosition) { - when (currentPosition) { - 0 -> { - if (scrolledPixList.size > 1 && scrolledPixList.last() == 0 || scrolledPixList.last() - scrolledPixList[0] > 0) { - //有可能出现滑到一半放弃的情况也是可以出现currentPosition == oldPositon=0,则先判断是否是往右滑时放弃 - return - } - //若还有上一个bottom fragment页面则切换 - mainActivity.viewPager.currentItem.takeIf { it > 0 } - ?.also { mainActivity.viewPager.setCurrentItem(it - 1, true) } - } - - (viewPagerBookshelf.adapter as FragmentStateAdapter).itemCount - 1 -> { - //若还有下一个bottom fragment页面则切换 - mainActivity.viewPager.currentItem.takeIf { it < mainActivity.viewPager.adapter!!.itemCount - 1 } - ?.also { mainActivity.viewPager.setCurrentItem(it + 1, true) } - } - } - } - oldPosition = currentPosition - scrolledPixList.clear()//清空滑动记录 - } - } - - }) + tabLayout.setupWithViewPager(binding.viewPagerBookshelf) + binding.viewPagerBookshelf.offscreenPageLimit = 1 + adapter = TabFragmentPageAdapter(childFragmentManager) + binding.viewPagerBookshelf.adapter = adapter } private fun initBookGroupData() { @@ -199,7 +141,7 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b if (data != bookGroups) { bookGroups.clear() bookGroups.addAll(data) - binding.viewPagerBookshelf.adapter?.notifyDataSetChanged() + adapter.notifyDataSetChanged() selectLastTab() } } @@ -309,21 +251,29 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b } } - private inner class TabFragmentPageAdapter : - FragmentStateAdapter(this) { + private inner class TabFragmentPageAdapter(fm: FragmentManager) : + FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { + + override fun getPageTitle(position: Int): CharSequence { + return bookGroups[position].groupName + } + + override fun getItemPosition(`object`: Any): Int { + return POSITION_NONE + } - override fun getItemId(position: Int): Long { + override fun getItem(position: Int): Fragment { val group = bookGroups[position] - return group.groupId + return BooksFragment.newInstance(position, group.groupId) } - override fun getItemCount(): Int { + override fun getCount(): Int { return bookGroups.size } - override fun createFragment(position: Int): Fragment { + override fun instantiateItem(container: ViewGroup, position: Int): Any { + val fragment = super.instantiateItem(container, position) as BooksFragment val group = bookGroups[position] - val fragment = BooksFragment.newInstance(position, group.groupId) fragmentMap[group.groupId] = fragment return fragment } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 80c952ab8..a387ecb36 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,7 +5,7 @@ android:layout_height="match_parent" android:orientation="vertical"> - -