Skip to content

Commit

Permalink
feat: 新增NestTabView下拉刷新相关属性
Browse files Browse the repository at this point in the history
  • Loading branch information
mahaaoo committed Nov 25, 2024
1 parent 420c4ac commit 5efff18
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 58 deletions.
22 changes: 19 additions & 3 deletions example/src/pages/NestedTabViewExample.tsx
Original file line number Diff line number Diff line change
@@ -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<TabViewExampleProps> = (props) => {
const {} = props;
const ref = useRef();
const [refreshing, setRefreshing] = useState(false);

useEffect(() => {
const autoScroll = () => {
Expand All @@ -16,7 +17,19 @@ const HeadTabViewExample: React.FC<TabViewExampleProps> = (props) => {
}, 2000);
};
// autoScroll();
}, [])
}, []);

const handleRefresh = () => {
console.log('下拉刷新开始');
setRefreshing(true);
const end = () => {
setTimeout(() => {
console.log('下拉刷新结束');
setRefreshing(false);
}, 2000);
};
end();
};

return (
<NestedTabView
Expand Down Expand Up @@ -61,6 +74,9 @@ const HeadTabViewExample: React.FC<TabViewExampleProps> = (props) => {
)}
tabs={['tab1', 'tab2', '第三个tabs']}
tabBarflex={'equal-width'}
refreshing={refreshing}
refreshControl={() => <NestedRefresh />}
onRefresh={handleRefresh}
>
<Nested.ScrollView contentContainerStyle={{ backgroundColor: 'orange' }}>
{new Array(80).fill(0).map((item, index) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,7 +25,7 @@ interface NormalControlProps {
};
}

const NormalControl: React.FC<NormalControlProps> = (props) => {
const NestedRefresh: React.FC<NestedRefreshProps> = (props) => {
const {
textConfig = {
normal: '下拉刷新',
Expand Down Expand Up @@ -103,4 +103,4 @@ const styles = StyleSheet.create({
},
});

export default NormalControl;
export default NestedRefresh;
75 changes: 28 additions & 47 deletions src/components/NestedTabView/NestedTabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, {
useCallback,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from 'react';
Expand All @@ -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<NestedTabViewRef, NestedTabViewProps>(
(props, ref) => {
Expand All @@ -48,6 +49,10 @@ const NestedTabView = forwardRef<NestedTabViewRef, NestedTabViewProps>(
style,
tabProps,
pageProps,
triggerHeight = 100 * 2,
refreshing = false,
refreshControl,
onRefresh,
onTabPress,
onPageSelected,
onPageScroll,
Expand Down Expand Up @@ -76,14 +81,16 @@ const NestedTabView = forwardRef<NestedTabViewRef, NestedTabViewProps>(
const [headerHeight, setHeaderHeight] = useState(0);
const refreshStatus = useSharedValue<RefreshStatus>(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) => {
Expand All @@ -92,9 +99,10 @@ const NestedTabView = forwardRef<NestedTabViewRef, NestedTabViewProps>(
);

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) {
Expand All @@ -113,27 +121,12 @@ const NestedTabView = forwardRef<NestedTabViewRef, NestedTabViewProps>(
)
);
}
}, [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,
Expand Down Expand Up @@ -182,20 +175,6 @@ const NestedTabView = forwardRef<NestedTabViewRef, NestedTabViewProps>(
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])
Expand All @@ -215,14 +194,15 @@ const NestedTabView = forwardRef<NestedTabViewRef, NestedTabViewProps>(
integralYOffset.value = integralY.value;
})
.onUpdate(({ translationY }) => {
if (!needRefresh) return;
const temp = translationY + integralYOffset.value;
if (temp > 0) {
if (sharedTranslate.value > 0) {
sharedTranslate.value = 0;
}
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;
Expand All @@ -233,18 +213,19 @@ const NestedTabView = forwardRef<NestedTabViewRef, NestedTabViewProps>(
}
})
.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,
{
Expand All @@ -258,7 +239,7 @@ const NestedTabView = forwardRef<NestedTabViewRef, NestedTabViewProps>(
);
}
} else {
if (integralY.value >= TRIGGERHEIGHT) {
if (integralY.value >= triggerHeight) {
// 这里触发下拉刷新
runOnJS(handleRefresh)();
} else {
Expand Down Expand Up @@ -431,9 +412,9 @@ const NestedTabView = forwardRef<NestedTabViewRef, NestedTabViewProps>(
<RefreshController
scrollOffset={integralY}
refreshStatus={refreshStatus}
triggerHeight={TRIGGERHEIGHT}
triggerHeight={triggerHeight}
>
<NormalRefresh />
{refreshControl && refreshControl()}
</RefreshController>
</NestedContext.Provider>
);
Expand Down
8 changes: 8 additions & 0 deletions src/components/NestedTabView/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ export const useVerifyProps = (
style,
renderHeader,
stickyHeight,
triggerHeight,
refreshing,
refreshControl,
onRefresh,
children,
} = props;

Expand Down Expand Up @@ -194,7 +198,11 @@ export const useVerifyProps = (
renderHeader,
stickyHeight,
initialIndex,
triggerHeight,
refreshing,
refreshControl,

onRefresh,
onTabPress,
onPageScroll,
onPageScrollStateChanged,
Expand Down
8 changes: 5 additions & 3 deletions src/components/NestedTabView/index.tsx
Original file line number Diff line number Diff line change
@@ -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<ScrollViewProps> = (props: any) => {
const AnimateScrollView = Animated.ScrollView;
Expand All @@ -27,4 +29,4 @@ const Nested = {
FlatList: NestedFlatList,
};

export { NestedTabView, Nested };
export { NestedTabView, Nested, NestedRefresh };
12 changes: 11 additions & 1 deletion src/components/NestedTabView/type.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 {
Expand All @@ -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;
Expand Down Expand Up @@ -98,3 +106,5 @@ export interface RefreshControllerProps {

export interface RefreshControllerContextProps
extends Omit<RefreshControllerProps, 'children'> {}

export const RESET_TIMING_EASING = Easing.bezier(0.33, 1, 0.68, 1);
6 changes: 5 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

0 comments on commit 5efff18

Please sign in to comment.