Skip to content
This repository has been archived by the owner on Nov 27, 2022. It is now read-only.

Commit

Permalink
feat: add animateOnIndexChange to enable/disable animation
Browse files Browse the repository at this point in the history
  • Loading branch information
mlecoq committed Sep 28, 2022
1 parent 20b5062 commit d03d49d
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 22 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ You can also pass a boolean to enable lazy for all of the scenes:

```js
<TabView
lazy
lazy
/>
```

Expand Down Expand Up @@ -316,6 +316,10 @@ Callback which is called when the swipe gesture starts, i.e. the user touches th

Callback which is called when the swipe gesture ends, i.e. the user lifts their finger from the screen after the swipe gesture.

##### `animateOnIndexChange`

Function which determines whether the animation is executed on index change

##### `initialLayout`

Object containing the initial height and width of the screens. Passing this will improve the initial rendering performance. For most apps, this is a good default:
Expand Down
2 changes: 2 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import CustomIndicatorExample from './CustomIndicatorExample';
import CustomTabBarExample from './CustomTabBarExample';
import CoverflowExample from './CoverflowExample';
import TabBarGapExample from './TabBarGapExample';
import CustomAnimationExample from './CustomAnimationExample';

type ExampleComponentType = React.ComponentType<{}> & {
title: string;
Expand All @@ -43,6 +44,7 @@ const EXAMPLE_COMPONENTS: ExampleComponentType[] = [
CustomTabBarExample,
CoverflowExample,
TabBarGapExample,
CustomAnimationExample,
];

const ExampleList = () => {
Expand Down
87 changes: 87 additions & 0 deletions example/src/CustomAnimationExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import * as React from 'react';
import { StyleSheet } from 'react-native';
import {
TabView,
TabBar,
SceneMap,
NavigationState,
SceneRendererProps,
} from 'react-native-tab-view';
import Article from './Shared/Article';
import Albums from './Shared/Albums';
import Chat from './Shared/Chat';
import Contacts from './Shared/Contacts';

type State = NavigationState<{
key: string;
title: string;
}>;

const animateOnIndexChange = (currentIndex: number, nextIndex: number) => {
return Math.abs(currentIndex - nextIndex) === 1;
};

const CustomAnimationExample = () => {
const [index, onIndexChange] = React.useState(1);
const [routes] = React.useState([
{ key: 'article', title: 'Article' },
{ key: 'contacts', title: 'Contacts' },
{ key: 'albums', title: 'Albums' },
{ key: 'chat', title: 'Chat' },
]);

const renderTabBar = (
props: SceneRendererProps & { navigationState: State }
) => (
<TabBar
{...props}
scrollEnabled
indicatorStyle={styles.indicator}
style={styles.tabbar}
tabStyle={styles.tab}
labelStyle={styles.label}
/>
);

const renderScene = SceneMap({
albums: Albums,
contacts: Contacts,
article: Article,
chat: Chat,
});

return (
<TabView
lazy
navigationState={{
index,
routes,
}}
renderScene={renderScene}
renderTabBar={renderTabBar}
onIndexChange={onIndexChange}
animateOnIndexChange={animateOnIndexChange}
/>
);
};

CustomAnimationExample.title = 'Custom Animation';
CustomAnimationExample.backgroundColor = '#3f51b5';
CustomAnimationExample.appbarElevation = 0;

export default CustomAnimationExample;

const styles = StyleSheet.create({
tabbar: {
backgroundColor: '#3f51b5',
},
tab: {
width: 'auto',
},
indicator: {
backgroundColor: '#ffeb3b',
},
label: {
fontWeight: '400',
},
});
24 changes: 17 additions & 7 deletions src/PagerViewAdapter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export default function PagerViewAdapter<T extends Route>({
onSwipeStart,
onSwipeEnd,
children,
animateOnIndexChange,
style,
...rest
}: Props<T>) {
Expand All @@ -58,13 +59,22 @@ export default function PagerViewAdapter<T extends Route>({
navigationStateRef.current = navigationState;
});

const jumpTo = React.useCallback((key: string) => {
const index = navigationStateRef.current.routes.findIndex(
(route: { key: string }) => route.key === key
);

pagerRef.current?.setPage(index);
}, []);
const jumpTo = React.useCallback(
(key: string) => {
const index = navigationStateRef.current.routes.findIndex(
(route: { key: string }) => route.key === key
);
if (
animateOnIndexChange &&
!animateOnIndexChange(indexRef.current, index)
) {
pagerRef.current?.setPageWithoutAnimation(index);
} else {
pagerRef.current?.setPage(index);
}
},
[animateOnIndexChange]
);

React.useEffect(() => {
if (keyboardDismissMode === 'auto') {
Expand Down
36 changes: 22 additions & 14 deletions src/PanResponderAdapter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export default function PanResponderAdapter<T extends Route>({
onSwipeStart,
onSwipeEnd,
children,
animateOnIndexChange,
style,
}: Props<T>) {
const { routes, index } = navigationState;
Expand All @@ -80,23 +81,30 @@ export default function PanResponderAdapter<T extends Route>({
const offset = -index * layoutRef.current.width;

const { timing, ...transitionConfig } = DefaultTransitionSpec;

Animated.parallel([
timing(panX, {
...transitionConfig,
toValue: offset,
useNativeDriver: false,
}),
]).start(({ finished }) => {
if (finished) {
onIndexChangeRef.current(index);
pendingIndexRef.current = undefined;
}
});
if (
animateOnIndexChange &&
!animateOnIndexChange(currentIndexRef.current, index)
) {
onIndexChangeRef.current(index);
pendingIndexRef.current = undefined;
} else {
Animated.parallel([
timing(panX, {
...transitionConfig,
toValue: offset,
useNativeDriver: false,
}),
]).start(({ finished }) => {
if (finished) {
onIndexChangeRef.current(index);
pendingIndexRef.current = undefined;
}
});
}

pendingIndexRef.current = index;
},
[panX]
[animateOnIndexChange, panX]
);

React.useEffect(() => {
Expand Down
2 changes: 2 additions & 0 deletions src/TabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default function TabView<T extends Route>({
style,
swipeEnabled = true,
tabBarPosition = 'top',
animateOnIndexChange,
}: Props<T>) {
const [layout, setLayout] = React.useState({
width: 0,
Expand Down Expand Up @@ -87,6 +88,7 @@ export default function TabView<T extends Route>({
onSwipeEnd={onSwipeEnd}
onIndexChange={jumpToIndex}
style={pagerStyle}
animateOnIndexChange={animateOnIndexChange}
>
{({ position, render, addEnterListener, jumpTo }) => {
// All of the props here must not change between re-renders
Expand Down
1 change: 1 addition & 0 deletions src/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ export type PagerProps = Omit<
swipeEnabled?: boolean;
onSwipeStart?: () => void;
onSwipeEnd?: () => void;
animateOnIndexChange?: (currentIndex: number, nextIndex: number) => boolean;
};

0 comments on commit d03d49d

Please sign in to comment.