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

pull/1023/head
gedoor 4 years ago
parent 10861ffe9f
commit 13b77657c3
  1. 60
      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
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
@ -40,7 +44,7 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
private var bookshelfReselected: Long = 0
private var exploreReselected: Long = 0
private var pagePosition = 0
private val fragmentMap = hashMapOf<Long, Fragment>()
private val fragmentMap = hashMapOf<Int, Fragment>()
private var bottomMenuCount = 2
private val realPositions = arrayOf(0, 1, 2, 3)
@ -54,8 +58,8 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
ATH.applyEdgeEffectColor(viewPagerMain)
ATH.applyBottomNavigationColor(bottomNavigationView)
viewPagerMain.offscreenPageLimit = 3
viewPagerMain.adapter = TabFragmentPageAdapter()
viewPagerMain.registerOnPageChangeCallback(PageChangeCallback())
viewPagerMain.adapter = TabFragmentPageAdapter(supportFragmentManager)
viewPagerMain.addOnPageChangeListener(PageChangeCallback())
bottomNavigationView.elevation =
if (AppConfig.elevation < 0) elevation else AppConfig.elevation.toFloat()
bottomNavigationView.setOnNavigationItemSelectedListener(this@MainActivity)
@ -110,10 +114,6 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
}
}
fun getViewPager(): ViewPager2 {
return binding.viewPagerMain
}
private fun upVersion() {
if (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) {
pagePosition = position
binding.bottomNavigationView.menu
.getItem(realPositions[position]).isChecked = true
}
}
private inner class TabFragmentPageAdapter :
FragmentStateAdapter(this) {
@Suppress("DEPRECATION")
private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun containsItem(itemId: Long): Boolean {
return fragmentMap.containsKey(itemId)
private fun getId(position: Int): Int {
return realPositions[position]
}
override fun getItemCount(): Int {
return bottomMenuCount
override fun getItemPosition(`object`: Any): Int {
return POSITION_NONE
}
override fun getItemId(position: Int): Long {
return realPositions[position].toLong()
}
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 bottomMenuCount
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val fragment = super.instantiateItem(container, position) as Fragment
fragmentMap[getId(position)] = fragment
return fragment
}

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

@ -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,
BaseBooksAdapter.CallBack {

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

@ -1,5 +1,5 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -13,9 +13,9 @@
app:contentLayout="@layout/view_tab_layout_min"
app:title="@string/bookshelf" />
<androidx.viewpager2.widget.ViewPager2
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager_bookshelf"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</io.legado.app.ui.main.bookshelf.RootView>
</LinearLayout>
Loading…
Cancel
Save