react-native-reanimated-carousel
react-native-reanimated-carousel copied to clipboard
Actual RTL
Any plans to add full RTL support? In its current implementation (v 3.0.4), it is not quite how RTL works.
In RTL mode carousel starting point is on the right (its first slide, index 0), and its end is on the left.
I tried playing around with the source code and setting {transform: [{scaleX: -1}]} on a container, it kinda works, but messes up swipe direction.
scaleX -1 creating issue and android device. swipe left moves screen in right direction and vise versa.
I used data.reverse() and set defaultIndex to data.length - 1 and its working perfect.
also for pagination just set flex to row-reverse
I used
data.reverse()and set defaultIndex todata.length - 1and its working perfect.also for pagination just set flex to
row-reverse
That's one way to do it, although not quite sufficient for some cases. For example, when some logic depends on correct item indexes. In that case everything should be changed accordingly, which is not quite right from architecture standpoint.
Data passed to the component shouldn't be reversed conditionally, but module itself should do the job when RTL is enabled, otherwise the statement that it supports RTL is incorrect.
Any updates on this ?
Here's the patch for an actual RTL. No data or starting index manipulation is required.
Important note, for this to work you have to:
- Mirror the carousel view horizontally by passing
{transform: [{scaleX: -1}]}to style prop. - Use the same technique for each slide to compensate for carousel mirroring.
Works perfectly for my use case, i.e. adding/removing slides, scrolling etc. Not sure about infinite scroll mode. I haven't tested it thoroughly, but it seems to do the job.
The patch is meant to fix the scroll direction issue mentioned here by @MrQureshi
The patch:
diff --git a/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx b/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx
index 5bb7d7a..4c51c8e 100644
--- a/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx
+++ b/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx
@@ -15,6 +15,7 @@ import Animated, {
useSharedValue,
withDecay,
} from "react-native-reanimated";
+import {I18nManager} from "react-native"
import { Easing } from "./constants";
import { CTX } from "./store";
@@ -264,13 +265,16 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
touching.value = true;
const { translationX, translationY } = e;
const panTranslation = isHorizontal.value
- ? translationX
+ ? translationX * (I18nManager.isRTL ? -1 : 1)
: translationY;
+
if (!infinite) {
if ((translation.value > 0 || translation.value < -ctx.max)) {
const boundary = translation.value > 0 ? 0 : -ctx.max;
const fixed = boundary - ctx.panOffset;
- const dynamic = panTranslation - fixed;
+ const dynamic = I18nManager.isRTL
+ ? panTranslation + fixed
+ : panTranslation - fixed;
translation.value = boundary + dynamic * 0.5;
return;
}
@@ -285,7 +289,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => {
? velocityX
: velocityY;
scrollEndTranslation.value = isHorizontal.value
- ? translationX
+ ? translationX * (I18nManager.isRTL ? -1 : 1)
: translationY;
endWithSpring(onScrollEnd);
Here's the patch for an actual RTL. No data or starting index manipulation is required.
Important note, for this to work you have to:
1. Mirror the carousel view horizontally by passing `{transform: [{scaleX: -1}]}` to style prop. 2. Use the same technique for each slide to compensate for carousel mirroring.Works perfectly for my use case, i.e. adding/removing slides, scrolling etc. Not sure about infinite scroll mode. I haven't tested it thoroughly, but it seems to do the job.
The patch is meant to fix the scroll direction issue mentioned here by @MrQureshi
The patch:
diff --git a/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx b/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx index 5bb7d7a..4c51c8e 100644 --- a/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx +++ b/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx @@ -15,6 +15,7 @@ import Animated, { useSharedValue, withDecay, } from "react-native-reanimated"; +import {I18nManager} from "react-native" import { Easing } from "./constants"; import { CTX } from "./store"; @@ -264,13 +265,16 @@ const IScrollViewGesture: React.FC<Props> = (props) => { touching.value = true; const { translationX, translationY } = e; const panTranslation = isHorizontal.value - ? translationX + ? translationX * (I18nManager.isRTL ? -1 : 1) : translationY; + if (!infinite) { if ((translation.value > 0 || translation.value < -ctx.max)) { const boundary = translation.value > 0 ? 0 : -ctx.max; const fixed = boundary - ctx.panOffset; - const dynamic = panTranslation - fixed; + const dynamic = I18nManager.isRTL + ? panTranslation + fixed + : panTranslation - fixed; translation.value = boundary + dynamic * 0.5; return; } @@ -285,7 +289,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => { ? velocityX : velocityY; scrollEndTranslation.value = isHorizontal.value - ? translationX + ? translationX * (I18nManager.isRTL ? -1 : 1) : translationY; endWithSpring(onScrollEnd);
It's great to have it in main branch. This solution works for me; infinite mode works too.
@dohooo, could please take a look on this.
If needed we could create a PR.
I recently found out that using scaleX: -1 in some cases causes severe render bottlenecks on Android 11+ (There are a few issues on react-native repo, look it up). The solution would be to add scaleY in addition to scaleX. I added the following to both the Carousel container and each page: {transform: [{scaleX: -1}, {scaleY: -1}]}
Here's the patch for an actual RTL. No data or starting index manipulation is required.
Important note, for this to work you have to:
- Mirror the carousel view horizontally by passing
{transform: [{scaleX: -1}]}to style prop.- Use the same technique for each slide to compensate for carousel mirroring.
Works perfectly for my use case, i.e. adding/removing slides, scrolling etc. Not sure about infinite scroll mode. I haven't tested it thoroughly, but it seems to do the job.
The patch is meant to fix the scroll direction issue mentioned here by @MrQureshi
The patch:
diff --git a/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx b/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx index 5bb7d7a..4c51c8e 100644 --- a/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx +++ b/node_modules/react-native-reanimated-carousel/src/ScrollViewGesture.tsx @@ -15,6 +15,7 @@ import Animated, { useSharedValue, withDecay, } from "react-native-reanimated"; +import {I18nManager} from "react-native" import { Easing } from "./constants"; import { CTX } from "./store"; @@ -264,13 +265,16 @@ const IScrollViewGesture: React.FC<Props> = (props) => { touching.value = true; const { translationX, translationY } = e; const panTranslation = isHorizontal.value - ? translationX + ? translationX * (I18nManager.isRTL ? -1 : 1) : translationY; + if (!infinite) { if ((translation.value > 0 || translation.value < -ctx.max)) { const boundary = translation.value > 0 ? 0 : -ctx.max; const fixed = boundary - ctx.panOffset; - const dynamic = panTranslation - fixed; + const dynamic = I18nManager.isRTL + ? panTranslation + fixed + : panTranslation - fixed; translation.value = boundary + dynamic * 0.5; return; } @@ -285,7 +289,7 @@ const IScrollViewGesture: React.FC<Props> = (props) => { ? velocityX : velocityY; scrollEndTranslation.value = isHorizontal.value - ? translationX + ? translationX * (I18nManager.isRTL ? -1 : 1) : translationY; endWithSpring(onScrollEnd);
Thank you so much. This works for me. Should not we have a PR for this?
@dohooo can you do this pls