viewPager2 3层嵌套有问题,书架换回viewPager

pull/1023/head
gedoor 4 years ago
parent 10861ffe9f
commit 13b77657c3
  1. 58
      app/src/main/java/io/legado/app/ui/main/MainActivity.kt
  2. 45
      app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt
  3. 82
      app/src/main/java/io/legado/app/ui/main/bookshelf/RootView.kt
  4. 2
      app/src/main/java/io/legado/app/ui/main/bookshelf1/BookshelfFragment1.kt
  5. 2
      app/src/main/res/layout/activity_main.xml
  6. 6
      app/src/main/res/layout/fragment_bookshelf.xml

@ -1,12 +1,16 @@
@file:Suppress("DEPRECATION")
package io.legado.app.ui.main package io.legado.app.ui.main
import android.os.Bundle import android.os.Bundle
import android.view.KeyEvent import android.view.KeyEvent
import android.view.MenuItem import android.view.MenuItem
import android.view.ViewGroup
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.fragment.app.FragmentManager
import androidx.viewpager2.widget.ViewPager2 import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.viewpager.widget.ViewPager
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import io.legado.app.BuildConfig import io.legado.app.BuildConfig
import io.legado.app.R import io.legado.app.R
@ -40,7 +44,7 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
private var bookshelfReselected: Long = 0 private var bookshelfReselected: Long = 0
private var exploreReselected: Long = 0 private var exploreReselected: Long = 0
private var pagePosition = 0 private var pagePosition = 0
private val fragmentMap = hashMapOf<Long, Fragment>() private val fragmentMap = hashMapOf<Int, Fragment>()
private var bottomMenuCount = 2 private var bottomMenuCount = 2
private val realPositions = arrayOf(0, 1, 2, 3) private val realPositions = arrayOf(0, 1, 2, 3)
@ -54,8 +58,8 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
ATH.applyEdgeEffectColor(viewPagerMain) ATH.applyEdgeEffectColor(viewPagerMain)
ATH.applyBottomNavigationColor(bottomNavigationView) ATH.applyBottomNavigationColor(bottomNavigationView)
viewPagerMain.offscreenPageLimit = 3 viewPagerMain.offscreenPageLimit = 3
viewPagerMain.adapter = TabFragmentPageAdapter() viewPagerMain.adapter = TabFragmentPageAdapter(supportFragmentManager)
viewPagerMain.registerOnPageChangeCallback(PageChangeCallback()) viewPagerMain.addOnPageChangeListener(PageChangeCallback())
bottomNavigationView.elevation = bottomNavigationView.elevation =
if (AppConfig.elevation < 0) elevation else AppConfig.elevation.toFloat() if (AppConfig.elevation < 0) elevation else AppConfig.elevation.toFloat()
bottomNavigationView.setOnNavigationItemSelectedListener(this@MainActivity) bottomNavigationView.setOnNavigationItemSelectedListener(this@MainActivity)
@ -110,10 +114,6 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
} }
} }
fun getViewPager(): ViewPager2 {
return binding.viewPagerMain
}
private fun upVersion() { private fun upVersion() {
if (LocalConfig.versionCode != appInfo.versionCode) { if (LocalConfig.versionCode != appInfo.versionCode) {
LocalConfig.versionCode = appInfo.versionCode LocalConfig.versionCode = appInfo.versionCode
@ -210,38 +210,44 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
} }
} }
private inner class PageChangeCallback : ViewPager2.OnPageChangeCallback() { private inner class PageChangeCallback : ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
pagePosition = position pagePosition = position
binding.bottomNavigationView.menu binding.bottomNavigationView.menu
.getItem(realPositions[position]).isChecked = true .getItem(realPositions[position]).isChecked = true
} }
} }
private inner class TabFragmentPageAdapter : @Suppress("DEPRECATION")
FragmentStateAdapter(this) { private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun containsItem(itemId: Long): Boolean { private fun getId(position: Int): Int {
return fragmentMap.containsKey(itemId) return realPositions[position]
} }
override fun getItemCount(): Int { override fun getItemPosition(`object`: Any): Int {
return bottomMenuCount return POSITION_NONE
} }
override fun getItemId(position: Int): Long { override fun getItem(position: Int): Fragment {
return realPositions[position].toLong() return when (getId(position)) {
0 -> BookshelfFragment()
1 -> ExploreFragment()
2 -> RssFragment()
else -> MyFragment()
}
} }
override fun createFragment(position: Int): Fragment { override fun getCount(): Int {
val id = getItemId(position) return bottomMenuCount
val fragment = when (id) {
0L -> BookshelfFragment()
1L -> ExploreFragment()
2L -> RssFragment()
else -> MyFragment()
} }
fragmentMap[id] = fragment
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val fragment = super.instantiateItem(container, position) as Fragment
fragmentMap[getId(position)] = fragment
return fragment return fragment
} }

@ -5,14 +5,11 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment import androidx.fragment.app.*
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
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.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseFragment import io.legado.app.base.VMBaseFragment
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
@ -22,7 +19,6 @@ import io.legado.app.data.entities.BookGroup
import io.legado.app.databinding.DialogBookshelfConfigBinding import io.legado.app.databinding.DialogBookshelfConfigBinding
import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.databinding.DialogEditTextBinding
import io.legado.app.databinding.FragmentBookshelfBinding import io.legado.app.databinding.FragmentBookshelfBinding
import io.legado.app.help.AppConfig
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.accentColor
@ -48,7 +44,7 @@ class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_b
private val binding by viewBinding(FragmentBookshelfBinding::bind) private val binding by viewBinding(FragmentBookshelfBinding::bind)
override val viewModel: BookshelfViewModel by viewModels() override val viewModel: BookshelfViewModel by viewModels()
private val activityViewModel: MainViewModel by activityViewModels() private val activityViewModel: MainViewModel by activityViewModels()
private lateinit var adapter: FragmentStateAdapter private lateinit var adapter: FragmentStatePagerAdapter
private lateinit var tabLayout: TabLayout private lateinit var tabLayout: TabLayout
private var bookGroupLiveData: LiveData<List<BookGroup>>? = null private var bookGroupLiveData: LiveData<List<BookGroup>>? = null
private val bookGroups = mutableListOf<BookGroup>() private val bookGroups = mutableListOf<BookGroup>()
@ -109,12 +105,10 @@ class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_b
tabLayout.isTabIndicatorFullWidth = false tabLayout.isTabIndicatorFullWidth = false
tabLayout.tabMode = TabLayout.MODE_SCROLLABLE tabLayout.tabMode = TabLayout.MODE_SCROLLABLE
tabLayout.setSelectedTabIndicatorColor(requireContext().accentColor) tabLayout.setSelectedTabIndicatorColor(requireContext().accentColor)
tabLayout.setupWithViewPager(binding.viewPagerBookshelf)
binding.viewPagerBookshelf.offscreenPageLimit = 1 binding.viewPagerBookshelf.offscreenPageLimit = 1
adapter = TabFragmentPageAdapter() adapter = TabFragmentPageAdapter(childFragmentManager)
binding.viewPagerBookshelf.adapter = adapter binding.viewPagerBookshelf.adapter = adapter
TabLayoutMediator(tabLayout, binding.viewPagerBookshelf) { tab, i ->
tab.text = bookGroups[i].groupName
}.attach()
} }
private fun initBookGroupData() { private fun initBookGroupData() {
@ -169,7 +163,6 @@ class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_b
.apply { .apply {
rgLayout.checkByIndex(bookshelfLayout) rgLayout.checkByIndex(bookshelfLayout)
rgSort.checkByIndex(bookshelfSort) rgSort.checkByIndex(bookshelfSort)
swShowUnread.isChecked = AppConfig.showUnread
} }
customView { alertBinding.root } customView { alertBinding.root }
okButton { okButton {
@ -183,10 +176,6 @@ class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_b
putPrefInt(PreferKey.bookshelfSort, rgSort.getCheckedIndex()) putPrefInt(PreferKey.bookshelfSort, rgSort.getCheckedIndex())
changed = true changed = true
} }
if (AppConfig.showUnread != swShowUnread.isChecked) {
AppConfig.showUnread = swShowUnread.isChecked
changed = true
}
if (changed) { if (changed) {
activity?.recreate() activity?.recreate()
} }
@ -249,25 +238,29 @@ class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_b
}.show() }.show()
} }
private inner class TabFragmentPageAdapter : private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentStateAdapter(this) { FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItemId(position: Int): Long { override fun getPageTitle(position: Int): CharSequence {
val group = bookGroups[position] return bookGroups[position].groupName
return group.groupId
} }
override fun containsItem(itemId: Long): Boolean { override fun getItemPosition(`object`: Any): Int {
return fragmentMap.containsKey(itemId) return POSITION_NONE
}
override fun getItem(position: Int): Fragment {
val group = bookGroups[position]
return BooksFragment.newInstance(position, group.groupId)
} }
override fun getItemCount(): Int { override fun getCount(): Int {
return bookGroups.size 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 group = bookGroups[position]
val fragment = BooksFragment.newInstance(position, group.groupId)
fragmentMap[group.groupId] = fragment fragmentMap[group.groupId] = fragment
return fragment return fragment
} }

@ -1,82 +0,0 @@
package io.legado.app.ui.main.bookshelf
import android.content.Context
import android.gesture.GestureOverlayView.ORIENTATION_HORIZONTAL
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.widget.LinearLayout
import androidx.viewpager2.widget.ViewPager2
import io.legado.app.R
import io.legado.app.ui.main.MainActivity
import io.legado.app.utils.activity
import kotlin.math.absoluteValue
import kotlin.math.sign
class RootView : LinearLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
private val touchSlop = ViewConfiguration.get(context).scaledTouchSlop
private var initialX = 0f
private var initialY = 0f
private val parentViewPager: ViewPager2?
get() = (activity as? MainActivity)?.getViewPager()
private val childViewPager: View?
get() = findViewById(R.id.view_pager_bookshelf)
private fun canChildScroll(orientation: Int, delta: Float): Boolean {
val direction = -delta.sign.toInt()
return when (orientation) {
0 -> childViewPager?.canScrollHorizontally(direction) ?: false
1 -> childViewPager?.canScrollVertically(direction) ?: false
else -> throw IllegalArgumentException()
}
}
override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
handleInterceptTouchEvent(e)
return super.onInterceptTouchEvent(e)
}
private fun handleInterceptTouchEvent(e: MotionEvent) {
val orientation = parentViewPager?.orientation ?: return
// Early return if child can't scroll in same direction as parent
if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) {
return
}
if (e.action == MotionEvent.ACTION_DOWN) {
initialX = e.x
initialY = e.y
parent.requestDisallowInterceptTouchEvent(true)
} else if (e.action == MotionEvent.ACTION_MOVE) {
val dx = e.x - initialX
val dy = e.y - initialY
val isVpHorizontal = orientation == ORIENTATION_HORIZONTAL
// assuming ViewPager2 touch-slop is 2x touch-slop of child
val scaledDx = dx.absoluteValue * if (isVpHorizontal) .5f else 1f
val scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5f
if (scaledDx > touchSlop || scaledDy > touchSlop) {
if (isVpHorizontal == (scaledDy > scaledDx)) {
// Gesture is perpendicular, allow all parents to intercept
parent.requestDisallowInterceptTouchEvent(false)
} else {
// Gesture is parallel, query child if movement in that direction is possible
if (canChildScroll(orientation, if (isVpHorizontal) dx else dy)) {
// Child can scroll, disallow all parents to intercept
parent.requestDisallowInterceptTouchEvent(true)
} else {
// Child cannot scroll, allow all parents to intercept
parent.requestDisallowInterceptTouchEvent(false)
}
}
}
}
}
}

@ -48,7 +48,7 @@ import kotlin.math.max
/** /**
* 书架界面 * 书架界面
*/ */
class BookshelfFragment : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_bookshelf1), class BookshelfFragment1 : VMBaseFragment<BookshelfViewModel>(R.layout.fragment_bookshelf1),
SearchView.OnQueryTextListener, SearchView.OnQueryTextListener,
BaseBooksAdapter.CallBack { BaseBooksAdapter.CallBack {

@ -5,7 +5,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager_main" android:id="@+id/view_pager_main"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<io.legado.app.ui.main.bookshelf.RootView xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -13,9 +13,9 @@
app:contentLayout="@layout/view_tab_layout_min" app:contentLayout="@layout/view_tab_layout_min"
app:title="@string/bookshelf" /> app:title="@string/bookshelf" />
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager.widget.ViewPager
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" />
</io.legado.app.ui.main.bookshelf.RootView> </LinearLayout>
Loading…
Cancel
Save