Skip to content

Commit b997db4

Browse files
authored
Fix/carousel android rtl jumps (#2831)
* Formattings * Logic Changes * Fixed return * Moved the resesting inside the loop condition * Removed children array line from renderAccessibleLayout * reverted counter change * Fixes android scrolls to opposite direction * Changed standing page calculation * Set page control to use currentStandingPage * Last small changes
1 parent eec4a12 commit b997db4

File tree

1 file changed

+34
-32
lines changed

1 file changed

+34
-32
lines changed

src/components/carousel/index.tsx

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Carousel extends Component<CarouselProps, CarouselState> {
5252
const defaultPageWidth = props.loop || !props.pageWidth ? Constants.screenWidth : props.pageWidth;
5353
const pageHeight = props.pageHeight ?? Constants.screenHeight;
5454
this.isAutoScrolled = false;
55-
55+
5656
this.state = {
5757
containerWidth: undefined,
5858
// @ts-ignore (defaultProps)
@@ -195,28 +195,30 @@ class Carousel extends Component<CarouselProps, CarouselState> {
195195
}
196196

197197
goToPage(pageIndex: number, animated = true) {
198-
this.setState({currentPage: this.getCalcIndex(pageIndex)}, () => this.updateOffset(animated));
198+
this.setState({currentPage: pageIndex}, () => this.updateOffset(animated));
199199
}
200200

201201
goToNextPage() {
202202
const {currentPage} = this.state;
203203
const pagesCount = presenter.getChildrenLength(this.props);
204204
const {loop} = this.props;
205205
let nextPageIndex;
206-
207206
if (loop) {
207+
if (currentPage === pagesCount + 1) {
208+
this.goToPage(0, false);
209+
return;
210+
}
208211
nextPageIndex = currentPage + 1;
209212
} else {
210213
nextPageIndex = Math.min(pagesCount - 1, currentPage + 1);
211214
}
212215

213216
this.goToPage(nextPageIndex, true);
214-
215-
// in case of a loop, after we advanced right to the cloned first page,
216-
// we return silently to the real first page
217-
if (loop && currentPage === pagesCount) {
218-
this.goToPage(0, false);
219-
}
217+
// // in case of a loop, after we advanced right to the cloned first page,
218+
// // we return silently to the real first page
219+
// if (loop && currentPage === pagesCount) {
220+
// this.goToPage(0, false);
221+
// }
220222
}
221223

222224
getCalcIndex(index: number): number {
@@ -239,10 +241,8 @@ class Carousel extends Component<CarouselProps, CarouselState> {
239241
if (containerWidth) {
240242
const spacings = pageWidth === containerWidth ? 0 : this.getItemSpacings(this.props);
241243
const initialBreak = pageWidth - (containerWidth - pageWidth - spacings) / 2;
242-
const snapToOffsets = _.times(
243-
presenter.getChildrenLength(this.props),
244-
index => initialBreak + index * pageWidth + this.getContainerMarginHorizontal()
245-
);
244+
const snapToOffsets = _.times(presenter.getChildrenLength(this.props),
245+
index => initialBreak + index * pageWidth + this.getContainerMarginHorizontal());
246246
return snapToOffsets;
247247
}
248248
};
@@ -307,14 +307,13 @@ class Carousel extends Component<CarouselProps, CarouselState> {
307307
onMomentumScrollEnd = () => {
308308
// finished full page scroll
309309
const {currentStandingPage, currentPage} = this.state;
310-
const index = this.getCalcIndex(currentPage);
311310
const pagesCount = presenter.getChildrenLength(this.props);
312311

313-
if (index < pagesCount) {
314-
this.setState({currentStandingPage: index});
312+
if (currentPage < pagesCount) {
313+
this.setState({currentStandingPage: currentPage});
315314

316-
if (currentStandingPage !== index) {
317-
this.props.onChangePage?.(index, currentStandingPage, {isAutoScrolled: this.isAutoScrolled});
315+
if (currentStandingPage !== currentPage) {
316+
this.props.onChangePage?.(currentPage, currentStandingPage, {isAutoScrolled: this.isAutoScrolled});
318317
this.isAutoScrolled = false;
319318
}
320319
}
@@ -355,10 +354,11 @@ class Carousel extends Component<CarouselProps, CarouselState> {
355354
};
356355

357356
onScrollEvent = Animated.event([
358-
{nativeEvent:
359-
{contentOffset:
360-
// @ts-ignore
361-
{y: this.props?.animatedScrollOffset?.y, x: this.props?.animatedScrollOffset?.x}
357+
{
358+
nativeEvent: {
359+
contentOffset:
360+
// @ts-ignore
361+
{y: this.props?.animatedScrollOffset?.y, x: this.props?.animatedScrollOffset?.x}
362362
}
363363
}
364364
],
@@ -404,9 +404,10 @@ class Carousel extends Component<CarouselProps, CarouselState> {
404404
};
405405

406406
renderChildren() {
407-
const {children, loop} = this.props;
407+
const {children: propsChildren, loop} = this.props;
408408
const length = presenter.getChildrenLength(this.props);
409-
409+
const children =
410+
Constants.isRTL && Constants.isAndroid ? React.Children.toArray(propsChildren).reverse() : propsChildren;
410411
const childrenArray = React.Children.map(children, (child, index) => {
411412
return this.renderChild(child, `${index}`);
412413
});
@@ -423,6 +424,7 @@ class Carousel extends Component<CarouselProps, CarouselState> {
423424

424425
renderPageControl() {
425426
const {pageControlPosition, pageControlProps = {}} = this.props;
427+
const {currentStandingPage} = this.state;
426428

427429
if (pageControlPosition) {
428430
const {
@@ -447,7 +449,7 @@ class Carousel extends Component<CarouselProps, CarouselState> {
447449
color={color}
448450
{...others}
449451
numOfPages={pagesCount}
450-
currentPage={this.getCalcIndex(this.state.currentPage)}
452+
currentPage={currentStandingPage}
451453
/>
452454
);
453455
}
@@ -471,7 +473,6 @@ class Carousel extends Component<CarouselProps, CarouselState> {
471473

472474
renderAccessibleLayout() {
473475
const {containerStyle, children, testID} = this.props;
474-
475476
return (
476477
<View style={containerStyle} onLayout={this.onContainerLayout}>
477478
<ScrollView
@@ -492,20 +493,17 @@ class Carousel extends Component<CarouselProps, CarouselState> {
492493
}
493494

494495
renderCarousel() {
495-
const {containerStyle, animated, horizontal, animatedScrollOffset, ...others} = this.props;
496+
const {containerStyle, animated, horizontal, animatedScrollOffset, style, ...others} = this.props;
496497
const scrollContainerStyle = this.shouldUsePageWidth()
497498
? {paddingRight: this.getItemSpacings(this.props)}
498499
: undefined;
499500
const snapToOffsets = this.getSnapToOffsets();
500501
const marginBottom = Math.max(0, this.getContainerPaddingVertical() - 16);
501502
const ScrollContainer = animatedScrollOffset ? Animated.ScrollView : ScrollView;
502503
const contentOffset = this.getInitialContentOffset(snapToOffsets);
504+
const _style = Constants.isRTL && Constants.isAndroid ? [styles.invertedView, style] : style;
503505
return (
504-
<View
505-
animated={animated}
506-
style={[{marginBottom}, containerStyle]}
507-
onLayout={this.onContainerLayout}
508-
>
506+
<View animated={animated} style={[{marginBottom}, containerStyle]} onLayout={this.onContainerLayout}>
509507
<ScrollContainer
510508
showsHorizontalScrollIndicator={false}
511509
showsVerticalScrollIndicator={false}
@@ -521,6 +519,7 @@ class Carousel extends Component<CarouselProps, CarouselState> {
521519
contentOffset={contentOffset}
522520
// onContentSizeChange={this.onContentSizeChange}
523521
onMomentumScrollEnd={this.onMomentumScrollEnd}
522+
style={_style}
524523
>
525524
{this.renderChildren()}
526525
</ScrollContainer>
@@ -556,5 +555,8 @@ const styles = StyleSheet.create({
556555
hiddenText: {
557556
position: 'absolute',
558557
width: 1
558+
},
559+
invertedView: {
560+
transform: [{scaleX: -1}]
559561
}
560562
});

0 commit comments

Comments
 (0)