diff --git a/example/src/pages/NestedTabViewExample.tsx b/example/src/pages/NestedTabViewExample.tsx index 8ffa80f..7a78d7f 100644 --- a/example/src/pages/NestedTabViewExample.tsx +++ b/example/src/pages/NestedTabViewExample.tsx @@ -1,12 +1,13 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { View, Text } from 'react-native'; -import { NestedTabView, Nested } from 'react-native-maui'; +import { NestedTabView, Nested, NestedRefresh } from 'react-native-maui'; interface TabViewExampleProps {} const HeadTabViewExample: React.FC = (props) => { const {} = props; const ref = useRef(); + const [refreshing, setRefreshing] = useState(false); useEffect(() => { const autoScroll = () => { @@ -16,7 +17,19 @@ const HeadTabViewExample: React.FC = (props) => { }, 2000); }; // autoScroll(); - }, []) + }, []); + + const handleRefresh = () => { + console.log('下拉刷新开始'); + setRefreshing(true); + const end = () => { + setTimeout(() => { + console.log('下拉刷新结束'); + setRefreshing(false); + }, 2000); + }; + end(); + }; return ( = (props) => { )} tabs={['tab1', 'tab2', '第三个tabs']} tabBarflex={'equal-width'} + refreshing={refreshing} + refreshControl={() => } + onRefresh={handleRefresh} > {new Array(80).fill(0).map((item, index) => { diff --git a/src/components/NestedTabView/NormalRefresh.tsx b/src/components/NestedTabView/NestedRefresh.tsx similarity index 95% rename from src/components/NestedTabView/NormalRefresh.tsx rename to src/components/NestedTabView/NestedRefresh.tsx index d96d5ae..c822518 100644 --- a/src/components/NestedTabView/NormalRefresh.tsx +++ b/src/components/NestedTabView/NestedRefresh.tsx @@ -16,7 +16,7 @@ import { Icon } from '../Icon'; import { Loading } from '../Loading'; import { useRefreshController } from './hooks'; -interface NormalControlProps { +interface NestedRefreshProps { textConfig?: { normal: string; release: string; @@ -25,7 +25,7 @@ interface NormalControlProps { }; } -const NormalControl: React.FC = (props) => { +const NestedRefresh: React.FC = (props) => { const { textConfig = { normal: '下拉刷新', @@ -103,4 +103,4 @@ const styles = StyleSheet.create({ }, }); -export default NormalControl; +export default NestedRefresh; diff --git a/src/components/NestedTabView/NestedTabView.tsx b/src/components/NestedTabView/NestedTabView.tsx index 2792e57..527774d 100644 --- a/src/components/NestedTabView/NestedTabView.tsx +++ b/src/components/NestedTabView/NestedTabView.tsx @@ -3,6 +3,7 @@ import React, { useCallback, useEffect, useImperativeHandle, + useMemo, useRef, useState, } from 'react'; @@ -23,20 +24,20 @@ import Animated, { withTiming, withDelay, runOnJS, - Easing, } from 'react-native-reanimated'; import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import { TabBar, TabBarRef } from '../TabBar'; import { PageStateType, PageView, PageViewRef } from '../PageView'; import { NestedContext, useNestRegister, useVerifyProps } from './hooks'; import { mscrollTo } from './util'; -import { NestedTabViewProps, NestedTabViewRef, RefreshStatus } from './type'; +import { + NestedTabViewProps, + NestedTabViewRef, + RefreshStatus, + RESET_TIMING_EASING, +} from './type'; import { isInteger } from '../../utils/typeUtil'; import RefreshController from './RefreshController'; -import NormalRefresh from './NormalRefresh'; - -const TRIGGERHEIGHT = 100 * 2; -const RESET_TIMING_EASING = Easing.bezier(0.33, 1, 0.68, 1); const NestedTabView = forwardRef( (props, ref) => { @@ -48,6 +49,10 @@ const NestedTabView = forwardRef( style, tabProps, pageProps, + triggerHeight = 100 * 2, + refreshing = false, + refreshControl, + onRefresh, onTabPress, onPageSelected, onPageScroll, @@ -76,14 +81,16 @@ const NestedTabView = forwardRef( const [headerHeight, setHeaderHeight] = useState(0); const refreshStatus = useSharedValue(RefreshStatus.Idle); - const [refreshing, setRefreshing] = useState(false); - const isRefreshing = useDerivedValue(() => { return !( integralY.value === 0 && refreshStatus.value === RefreshStatus.Idle ); }, [refreshStatus, integralY]); + const needRefresh = useMemo(() => { + return !!refreshControl; + }, [refreshControl]); + useAnimatedReaction( () => isRefreshing.value, (isRefreshing) => { @@ -92,9 +99,10 @@ const NestedTabView = forwardRef( ); useEffect(() => { + if (!needRefresh) return; if (refreshing) { refreshStatus.value = RefreshStatus.Holding; - integralY.value = withTiming(TRIGGERHEIGHT, { + integralY.value = withTiming(triggerHeight, { easing: RESET_TIMING_EASING, }); } else if (refreshStatus.value !== RefreshStatus.Idle) { @@ -113,27 +121,12 @@ const NestedTabView = forwardRef( ) ); } - }, [refreshing]); + }, [refreshing, needRefresh]); const handleRefresh = () => { - console.log('下拉刷新开始'); - setRefreshing(true); - const end = () => { - setTimeout(() => { - console.log('下拉刷新结束'); - setRefreshing(false); - }, 2000); - }; - end(); + onRefresh && onRefresh(); }; - useAnimatedReaction( - () => refreshStatus.value, - (value) => { - console.log(value); - } - ); - const { isReady, childInfo, @@ -182,20 +175,6 @@ const NestedTabView = forwardRef( cancelAnimation(sharedTranslate); }; - // useAnimatedReaction( - // () => integralY.value, - // (value) => { - // console.log(value); - // } - // ); - - // useAnimatedReaction( - // () => sharedTranslate.value, - // (value) => { - // console.log(value); - // } - // ); - const panGesture = Gesture.Pan() .withRef(totalRef) .activeOffsetX([-500, 500]) @@ -215,6 +194,7 @@ const NestedTabView = forwardRef( integralYOffset.value = integralY.value; }) .onUpdate(({ translationY }) => { + if (!needRefresh) return; const temp = translationY + integralYOffset.value; if (temp > 0) { if (sharedTranslate.value > 0) { @@ -222,7 +202,7 @@ const NestedTabView = forwardRef( } integralY.value = temp; if (!refreshing) { - if (Math.abs(integralY.value) >= TRIGGERHEIGHT) { + if (Math.abs(integralY.value) >= triggerHeight) { refreshStatus.value = RefreshStatus.Reached; } else { refreshStatus.value = RefreshStatus.Pulling; @@ -233,18 +213,19 @@ const NestedTabView = forwardRef( } }) .onEnd(() => { + if (!needRefresh) return; if (integralY.value < 0) return; if (refreshing) { // 在已经是下拉刷新的状态下,如果继续向下拉,则会回到默认的最大triggleHeight位置处 // 如果有向上收起的意图,则将下拉区全部收起 - if (integralY.value >= TRIGGERHEIGHT) { - integralY.value = withTiming(TRIGGERHEIGHT, { + if (integralY.value >= triggerHeight) { + integralY.value = withTiming(triggerHeight, { easing: RESET_TIMING_EASING, }); } else { // 这里要做一个snapPoint const dest = - integralY.value <= TRIGGERHEIGHT / 2 ? 0 : TRIGGERHEIGHT; + integralY.value <= triggerHeight / 2 ? 0 : triggerHeight; integralY.value = withTiming( dest, { @@ -258,7 +239,7 @@ const NestedTabView = forwardRef( ); } } else { - if (integralY.value >= TRIGGERHEIGHT) { + if (integralY.value >= triggerHeight) { // 这里触发下拉刷新 runOnJS(handleRefresh)(); } else { @@ -431,9 +412,9 @@ const NestedTabView = forwardRef( - + {refreshControl && refreshControl()} ); diff --git a/src/components/NestedTabView/hooks.ts b/src/components/NestedTabView/hooks.ts index f6dc56f..dd65520 100644 --- a/src/components/NestedTabView/hooks.ts +++ b/src/components/NestedTabView/hooks.ts @@ -132,6 +132,10 @@ export const useVerifyProps = ( style, renderHeader, stickyHeight, + triggerHeight, + refreshing, + refreshControl, + onRefresh, children, } = props; @@ -194,7 +198,11 @@ export const useVerifyProps = ( renderHeader, stickyHeight, initialIndex, + triggerHeight, + refreshing, + refreshControl, + onRefresh, onTabPress, onPageScroll, onPageScrollStateChanged, diff --git a/src/components/NestedTabView/index.tsx b/src/components/NestedTabView/index.tsx index 6a5ba1b..997e3dd 100644 --- a/src/components/NestedTabView/index.tsx +++ b/src/components/NestedTabView/index.tsx @@ -1,7 +1,9 @@ +import { ScrollViewProps, FlatListProps } from 'react-native'; +import Animated from 'react-native-reanimated'; + import NestedTabView from './NestedTabView'; import NestedScene from './NestedScene'; -import Animated from 'react-native-reanimated'; -import { ScrollViewProps, FlatListProps } from 'react-native'; +import NestedRefresh from './NestedRefresh'; const NestedScrollView: React.FC = (props: any) => { const AnimateScrollView = Animated.ScrollView; @@ -27,4 +29,4 @@ const Nested = { FlatList: NestedFlatList, }; -export { NestedTabView, Nested }; +export { NestedTabView, Nested, NestedRefresh }; diff --git a/src/components/NestedTabView/type.ts b/src/components/NestedTabView/type.ts index 0a35f00..235eff3 100644 --- a/src/components/NestedTabView/type.ts +++ b/src/components/NestedTabView/type.ts @@ -1,4 +1,4 @@ -import { SharedValue, AnimatedRef } from 'react-native-reanimated'; +import { SharedValue, AnimatedRef, Easing } from 'react-native-reanimated'; import { TabBarProps } from '../TabBar'; import { PageStateType, PageViewProps } from '../PageView'; import { ViewStyle } from 'react-native'; @@ -14,6 +14,10 @@ export interface NestedTabViewProps stickyHeight?: number; style?: ViewStyle; initialIndex?: number; + triggerHeight?: number; + refreshing?: boolean; + refreshControl?: () => React.ReactNode; + onRefresh?: () => void; } export interface NestedTabViewVerifyProps { @@ -28,7 +32,11 @@ export interface NestedTabViewVerifyProps { stickyHeight?: number; style?: ViewStyle; initialIndex?: number; + triggerHeight?: number; + refreshing?: boolean; + refreshControl?: () => React.ReactNode; + onRefresh?: () => void; onTabPress?: (index: number) => void; onPageScroll?: (translate: number) => void; onPageScrollStateChanged?: (state: PageStateType) => void; @@ -98,3 +106,5 @@ export interface RefreshControllerProps { export interface RefreshControllerContextProps extends Omit {} + +export const RESET_TIMING_EASING = Easing.bezier(0.33, 1, 0.68, 1); diff --git a/src/index.ts b/src/index.ts index 7b7dca0..13b5266 100644 --- a/src/index.ts +++ b/src/index.ts @@ -86,6 +86,10 @@ export { snapPoint, clamp } from './utils/redash'; export { Freeze } from './utils/Freeze'; export { TabView } from './components/TabView'; -export { NestedTabView, Nested } from './components/NestedTabView'; +export { + NestedTabView, + Nested, + NestedRefresh, +} from './components/NestedTabView'; export { PageView, PageViewRef } from './components/PageView'; export { TabBar, TabBarRef } from './components/TabBar';