diff --git a/android/src/main/java/com/reactnativepagerview/PagerViewViewManagerImpl.kt b/android/src/main/java/com/reactnativepagerview/PagerViewViewManagerImpl.kt index ad7ea468..d5b82ff9 100644 --- a/android/src/main/java/com/reactnativepagerview/PagerViewViewManagerImpl.kt +++ b/android/src/main/java/com/reactnativepagerview/PagerViewViewManagerImpl.kt @@ -4,10 +4,15 @@ import android.view.View import android.view.ViewGroup import androidx.viewpager2.widget.ViewPager2 import com.facebook.react.uimanager.PixelUtil +import android.os.Handler +import android.os.Looper +import android.view.Choreographer object PagerViewViewManagerImpl { const val NAME = "RNCViewPager" + private var refreshFrameCallback: Choreographer.FrameCallback? = null + fun getViewPager(view: NestedScrollableHost): ViewPager2 { if (view.getChildAt(0) is ViewPager2) { return view.getChildAt(0) as ViewPager2 @@ -78,8 +83,8 @@ object PagerViewViewManagerImpl { } adapter?.removeChildAt(index) - - refreshViewChildrenLayout(pager) + + debouncedRefreshViewChildrenLayout(pager) } fun needsCustomLayoutForChildren(): Boolean { @@ -157,9 +162,26 @@ object PagerViewViewManagerImpl { private fun refreshViewChildrenLayout(view: View) { view.post { view.measure( - View.MeasureSpec.makeMeasureSpec(view.width, View.MeasureSpec.EXACTLY), - View.MeasureSpec.makeMeasureSpec(view.height, View.MeasureSpec.EXACTLY)) + View.MeasureSpec.makeMeasureSpec(view.width, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(view.height, View.MeasureSpec.EXACTLY)) view.layout(view.left, view.top, view.right, view.bottom) } } + + private fun debouncedRefreshViewChildrenLayout(view: View) { + // Fixes https://github.com/callstack/react-native-pager-view/issues/946 + refreshFrameCallback?.let { Choreographer.getInstance().removeFrameCallback(it) } + + val adapter = (view as? ViewPager2)?.adapter as? ViewPagerAdapter + if (adapter == null || adapter.itemCount == 0) { + // Do not call refreshViewChildrenLayout on pager unmount + return + } + + refreshFrameCallback = Choreographer.FrameCallback { + refreshViewChildrenLayout(view) + refreshFrameCallback = null + } + Choreographer.getInstance().postFrameCallback(refreshFrameCallback) + } } \ No newline at end of file diff --git a/example/src/App.tsx b/example/src/App.tsx index 4295ff12..e84df5f7 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -95,7 +95,7 @@ const Stack = createStackNavigator(); const NativeStack = createNativeStackNavigator(); export function Navigation() { - const [mode, setMode] = React.useState<'native' | 'js'>('js'); + const [mode, setMode] = React.useState<'native' | 'js'>('native'); const NavigationStack = mode === 'js' ? Stack : NativeStack; return ( diff --git a/example/src/OnPageScrollExample.tsx b/example/src/OnPageScrollExample.tsx index 19dd4b3c..319f3d72 100644 --- a/example/src/OnPageScrollExample.tsx +++ b/example/src/OnPageScrollExample.tsx @@ -1,7 +1,6 @@ import React from 'react'; -import { StyleSheet, Text, View, SafeAreaView, Animated } from 'react-native'; +import { StyleSheet, Text, View, SafeAreaView, Animated, ScrollView, TouchableOpacity } from 'react-native'; import PagerView from 'react-native-pager-view'; -import { ScrollView, TouchableOpacity } from 'react-native-gesture-handler'; import { ProgressBar } from './component/ProgressBar'; import { useNavigationPanel } from './hook/useNavigationPanel';