Skip to content

Fix/page carousel RTL android #1612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 24, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/components/tabController/PageCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,39 @@ function PageCarousel({...props}) {
targetPage,
selectedIndex = 0,
pageWidth,
carouselOffset
carouselOffset,
setCurrentIndex
} = useContext(TabBarContext);
const contentOffset = useMemo(() => ({x: selectedIndex * pageWidth, y: 0}), [selectedIndex, pageWidth]);
const wasScrolledByPress = useSharedValue(false);
const indexChangeReason = useSharedValue<'byScroll' | 'byPress' | undefined>(undefined);

const scrollHandler = useAnimatedScrollHandler({
onScroll: e => {
carouselOffset.value = e.contentOffset.x;
const newIndex = e.contentOffset.x / pageWidth;

if (wasScrolledByPress.value) {
if (indexChangeReason.value === 'byPress') { // Scroll was immediate and not by gesture
/* Round is for android when offset value has fraction */
targetPage.value = withTiming(Math.round(newIndex));
wasScrolledByPress.value = false;
indexChangeReason.value = undefined;
} else {
targetPage.value = newIndex;
}
},
onMomentumEnd: e => {
const newPage = Math.round(e.contentOffset.x / pageWidth);
currentPage.value = newPage;
indexChangeReason.value = 'byScroll';
setCurrentIndex(newPage);
}
});

const scrollToItem = useCallback(index => {
wasScrolledByPress.value = true;
if (indexChangeReason.value === 'byScroll') {
indexChangeReason.value = undefined;
return;
}

indexChangeReason.value = 'byPress';
// @ts-expect-error
carousel.current?.scrollTo({x: index * pageWidth, animated: false});
},
Expand All @@ -56,7 +63,7 @@ function PageCarousel({...props}) {
return currentPage.value;
},
(currIndex, prevIndex) => {
if (currIndex !== prevIndex) {
if (prevIndex !== null && currIndex !== prevIndex) {
runOnJS(scrollToItem)(currIndex);
}
});
Expand Down
1 change: 1 addition & 0 deletions src/components/tabController/TabBarContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface TabControllerContext {
/** transition page index (can be a fraction when transitioning between pages) */
targetPage: Reanimated.SharedValue<number>;
carouselOffset: Reanimated.SharedValue<number>;
setCurrentIndex: (index: number) => void;
}

// @ts-expect-error
Expand Down
4 changes: 2 additions & 2 deletions src/components/tabController/TabBarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default function TabBarItem({
style,
...props
}: Props) {
const {currentPage} = useContext(TabBarContext);
const {currentPage, setCurrentIndex} = useContext(TabBarContext);
const itemRef = useRef();
const itemWidth = useRef(props.width);
// JSON.parse(JSON.stringify is due to an issue with reanimated
Expand All @@ -140,7 +140,7 @@ export default function TabBarItem({

const onPress = useCallback(() => {
if (!ignore) {
currentPage.value = index;
setCurrentIndex(index);
}

props.onPress?.(index);
Expand Down
12 changes: 9 additions & 3 deletions src/components/tabController/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// TODO: support commented props
import React, {PropsWithChildren, useMemo, useEffect, useRef, useState} from 'react';
import React, {PropsWithChildren, useMemo, useEffect, useRef, useState, useCallback} from 'react';
import _ from 'lodash';
import {useAnimatedReaction, useSharedValue, withTiming, runOnJS} from 'react-native-reanimated';
import {Constants} from '../../helpers';
Expand Down Expand Up @@ -95,14 +95,19 @@ function TabController({
const targetPage = useSharedValue(initialIndex);
const carouselOffset = useSharedValue(initialIndex * Math.round(pageWidth));

const setCurrentIndex = useCallback(index => {
'worklet';
currentPage.value = index;
}, []);

useEffect(() => {
if (!_.isUndefined(selectedIndex)) {
LogService.deprecationWarn({component: 'TabController2', oldProp: 'selectedIndex', newProp: 'initialIndex'});
}
}, [selectedIndex]);

useEffect(() => {
currentPage.value = initialIndex;
setCurrentIndex(initialIndex);
}, [initialIndex]);

useAnimatedReaction(() => {
Expand Down Expand Up @@ -130,7 +135,8 @@ function TabController({
carouselOffset,
containerWidth: screenWidth,
/* Callbacks */
onChangeIndex
onChangeIndex,
setCurrentIndex
};
}, [initialIndex, asCarousel, items, onChangeIndex, screenWidth]);

Expand Down