Skip to content

Commit d253b3c

Browse files
committed
fix: fixed scrolling on Android
1 parent d74d1be commit d253b3c

File tree

6 files changed

+102
-95
lines changed

6 files changed

+102
-95
lines changed

example/metro.config.js

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,37 @@ const pak = require('../package.json');
66
const root = path.resolve(__dirname, '..');
77

88
const modules = Object.keys({
9-
...pak.peerDependencies,
9+
...pak.peerDependencies,
1010
});
1111

1212
module.exports = {
13-
projectRoot: __dirname,
14-
watchFolders: [root],
13+
projectRoot: __dirname,
14+
watchFolders: [root],
1515

16-
// We need to make sure that only one version is loaded for peerDependencies
17-
// So we blacklist them at the root, and alias them to the versions in example's node_modules
18-
resolver: {
19-
blacklistRE: blacklist(
20-
modules.map(
21-
(m) =>
22-
new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)
23-
)
24-
),
16+
// We need to make sure that only one version is loaded for peerDependencies
17+
// So we blacklist them at the root, and alias them to the versions in example's node_modules
18+
resolver: {
19+
blacklistRE: blacklist(
20+
modules.map(
21+
(m) =>
22+
new RegExp(
23+
`^${escape(path.join(root, 'node_modules', m))}\\/.*$`
24+
)
25+
)
26+
),
2527

26-
extraNodeModules: modules.reduce((acc, name) => {
27-
acc[name] = path.join(__dirname, 'node_modules', name);
28-
return acc;
29-
}, {}),
30-
},
28+
extraNodeModules: modules.reduce((acc, name) => {
29+
acc[name] = path.join(__dirname, 'node_modules', name);
30+
return acc;
31+
}, {}),
32+
},
3133

32-
transformer: {
33-
getTransformOptions: async () => ({
34-
transform: {
35-
experimentalImportSupport: false,
36-
inlineRequires: true,
37-
},
38-
}),
39-
},
34+
transformer: {
35+
getTransformOptions: async () => ({
36+
transform: {
37+
experimentalImportSupport: false,
38+
inlineRequires: true,
39+
},
40+
}),
41+
},
4042
};

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@
2727
"babel-preset-expo": "8.3.0",
2828
"expo-cli": "^4.0.13",
2929
"react-native-gesture-handler": "^1.10.3",
30-
"react-native-reanimated": "^2.2.0"
30+
"react-native-reanimated": "2.2.0"
3131
}
3232
}

example/src/App.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ export default function App() {
2525
mode="parallax"
2626
width={width}
2727
data={[
28-
// { color: 'red' },
29-
// { color: 'purple' },
30-
// { color: 'blue' },
31-
// { color: 'yellow' },
28+
{ color: 'red' },
29+
{ color: 'purple' },
30+
{ color: 'blue' },
31+
{ color: 'yellow' },
3232
]}
3333
parallaxScrollingScale={0.8}
3434
onSnapToItem={(index) => {

example/yarn.lock

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,8 +1171,8 @@
11711171

11721172
"@egjs/hammerjs@^2.0.17":
11731173
version "2.0.17"
1174-
resolved "https://registry.npm.taobao.org/@egjs/hammerjs/download/@egjs/hammerjs-2.0.17.tgz#5dc02af75a6a06e4c2db0202cae38c9263895124"
1175-
integrity sha1-XcAq91pqBuTC2wICyuOMkmOJUSQ=
1174+
resolved "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz#5dc02af75a6a06e4c2db0202cae38c9263895124"
1175+
integrity sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==
11761176
dependencies:
11771177
"@types/hammerjs" "^2.0.36"
11781178

@@ -2301,8 +2301,8 @@
23012301

23022302
"@types/hammerjs@^2.0.36":
23032303
version "2.0.40"
2304-
resolved "https://registry.nlark.com/@types/hammerjs/download/@types/hammerjs-2.0.40.tgz#ded0240b6ea1ad7afc1e60374c49087aaea5dbd8"
2305-
integrity sha1-3tAkC26hrXr8HmA3TEkIeq6l29g=
2304+
resolved "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.40.tgz#ded0240b6ea1ad7afc1e60374c49087aaea5dbd8"
2305+
integrity sha512-VbjwR1fhsn2h2KXAY4oy1fm7dCxaKy0D+deTb8Ilc3Eo3rc5+5eA4rfYmZaHgNJKxVyI0f6WIXzO2zLkVmQPHA==
23062306

23072307
"@types/html-minifier-terser@^5.0.0":
23082308
version "5.1.2"
@@ -4465,8 +4465,8 @@ cron-parser@^2.13.0:
44654465

44664466
cross-fetch@^3.0.4:
44674467
version "3.1.4"
4468-
resolved "https://registry.nlark.com/cross-fetch/download/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
4469-
integrity sha1-lyPzo6JHv4uJA586OAqSROj6Lzk=
4468+
resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
4469+
integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==
44704470
dependencies:
44714471
node-fetch "2.6.1"
44724472

@@ -5950,8 +5950,8 @@ fbjs@^0.8.4:
59505950

59515951
fbjs@^3.0.0:
59525952
version "3.0.0"
5953-
resolved "https://registry.npm.taobao.org/fbjs/download/fbjs-3.0.0.tgz#0907067fb3f57a78f45d95f1eacffcacd623c165"
5954-
integrity sha1-CQcGf7P1enj0XZXx6s/8rNYjwWU=
5953+
resolved "https://registry.npmjs.org/fbjs/-/fbjs-3.0.0.tgz#0907067fb3f57a78f45d95f1eacffcacd623c165"
5954+
integrity sha512-dJd4PiDOFuhe7vk4F80Mba83Vr2QuK86FoxtgPmzBqEJahncp+13YCmfoa53KHCo6OnlXLG7eeMWPfB5CrpVKg==
59555955
dependencies:
59565956
cross-fetch "^3.0.4"
59575957
fbjs-css-vars "^1.0.0"
@@ -6729,8 +6729,8 @@ hmac-drbg@^1.0.1:
67296729

67306730
hoist-non-react-statics@^3.3.0:
67316731
version "3.3.2"
6732-
resolved "https://registry.npm.taobao.org/hoist-non-react-statics/download/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
6733-
integrity sha1-7OCsr3HWLClpwuxZ/v9CpLGoW0U=
6732+
resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
6733+
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
67346734
dependencies:
67356735
react-is "^16.7.0"
67366736

@@ -8931,8 +8931,8 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
89318931

89328932
mockdate@^3.0.2:
89338933
version "3.0.5"
8934-
resolved "https://registry.npm.taobao.org/mockdate/download/mockdate-3.0.5.tgz#789be686deb3149e7df2b663d2bc4392bc3284fb"
8935-
integrity sha1-eJvmht6zFJ598rZj0rxDkrwyhPs=
8934+
resolved "https://registry.npmjs.org/mockdate/-/mockdate-3.0.5.tgz#789be686deb3149e7df2b663d2bc4392bc3284fb"
8935+
integrity sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ==
89368936

89378937
moment-timezone@^0.5.31:
89388938
version "0.5.33"
@@ -9085,8 +9085,8 @@ nocache@^2.1.0:
90859085

90869086
90879087
version "2.6.1"
9088-
resolved "https://registry.nlark.com/node-fetch/download/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
9089-
integrity sha1-BFvTI2Mfdu0uK1VXM5RBa2OaAFI=
9088+
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
9089+
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
90909090

90919091
node-fetch@^1.0.1:
90929092
version "1.7.3"
@@ -10784,19 +10784,19 @@ react-is@^17.0.1:
1078410784

1078510785
react-native-gesture-handler@^1.10.3:
1078610786
version "1.10.3"
10787-
resolved "https://registry.npm.taobao.org/react-native-gesture-handler/download/react-native-gesture-handler-1.10.3.tgz#942bbf2963bbf49fa79593600ee9d7b5dab3cfc0"
10788-
integrity sha1-lCu/KWO79J+nlZNgDunXtdqzz8A=
10787+
resolved "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.10.3.tgz#942bbf2963bbf49fa79593600ee9d7b5dab3cfc0"
10788+
integrity sha512-cBGMi1IEsIVMgoox4RvMx7V2r6bNKw0uR1Mu1o7NbuHS6BRSVLq0dP34l2ecnPlC+jpWd3le6Yg1nrdCjby2Mw==
1078910789
dependencies:
1079010790
"@egjs/hammerjs" "^2.0.17"
1079110791
fbjs "^3.0.0"
1079210792
hoist-non-react-statics "^3.3.0"
1079310793
invariant "^2.2.4"
1079410794
prop-types "^15.7.2"
1079510795

10796-
react-native-reanimated@^2.2.0:
10796+
1079710797
version "2.2.0"
10798-
resolved "https://registry.nlark.com/react-native-reanimated/download/react-native-reanimated-2.2.0.tgz#a6412c56b4e591d1f00fac949f62d0c72c357c78"
10799-
integrity sha1-pkEsVrTlkdHwD6yUn2LQxyw1fHg=
10798+
resolved "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.2.0.tgz#a6412c56b4e591d1f00fac949f62d0c72c357c78"
10799+
integrity sha512-lOJDd+5w1gY6DHGXG2jD1dsjzQmXQ2699HUc3IztvI2WP4zUT+UAA+zSG+5JiBS5DUnTL8YhhkmUQmr1KNGO5w==
1080010800
dependencies:
1080110801
"@babel/plugin-transform-object-assign" "^7.10.4"
1080210802
fbjs "^3.0.0"
@@ -12012,8 +12012,8 @@ stream-shift@^1.0.0:
1201212012

1201312013
string-hash-64@^1.0.3:
1201412014
version "1.0.3"
12015-
resolved "https://registry.npm.taobao.org/string-hash-64/download/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322"
12016-
integrity sha1-DetW31hnhkDbXEecy7tZeqoN4yI=
12015+
resolved "https://registry.npmjs.org/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322"
12016+
integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw==
1201712017

1201812018
string-width@^1.0.1:
1201912019
version "1.0.2"

src/Carousel.tsx

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,15 @@ import Animated, {
1313
withTiming,
1414
} from 'react-native-reanimated';
1515
import { CarouselItem } from './CarouselItem';
16-
import { fillNum } from './fillNum';
1716
import type { TMode } from './layouts';
1817
import { ParallaxLayout } from './layouts/index';
1918
import { useCarouselController } from './useCarouselController';
2019
import { useComputedAnim } from './useComputedAnim';
2120
import { useLoop } from './useLoop';
2221
import { useComputedIndex } from './useComputedIndex';
2322

24-
export const _withTiming = (
25-
num: number,
26-
callback?: (isFinished: boolean) => void
27-
) => {
28-
'worklet';
29-
return withTiming(
30-
num,
31-
{
32-
duration: 250,
33-
},
34-
(isFinished) => {
35-
!!callback && runOnJS(callback)(isFinished);
36-
}
37-
);
23+
export const timingConfig = {
24+
duration: 250,
3825
};
3926

4027
export interface ICarouselProps<T extends unknown> {
@@ -211,70 +198,86 @@ function Carousel<T extends unknown = any>(
211198
useAnimatedGestureHandler<PanGestureHandlerGestureEvent>(
212199
{
213200
onStart: (_, ctx: any) => {
201+
if (ctx.lock) return;
214202
ctx.startContentOffsetX = handlerOffsetX.value;
203+
ctx.currentContentOffsetX = handlerOffsetX.value;
215204
},
216205
onActive: (e, ctx: any) => {
206+
if (ctx.lock) return;
207+
/**
208+
* `onActive` and `onEnd` return different values of translationX!So that creates a bias!TAT
209+
* */
210+
ctx.translationX = e.translationX;
217211
if (loop) {
218212
handlerOffsetX.value =
219-
ctx.startContentOffsetX +
220-
Math.round(e.translationX);
213+
ctx.currentContentOffsetX + e.translationX;
221214
return;
222215
}
223216
handlerOffsetX.value = Math.max(
224-
Math.min(
225-
ctx.startContentOffsetX +
226-
Math.round(e.translationX),
227-
0
228-
),
217+
Math.min(ctx.currentContentOffsetX + e.translationX, 0),
229218
-(data.length - 1) * width
230219
);
231220
},
232-
onEnd: (e) => {
233-
const intTranslationX = Math.round(e.translationX);
234-
const sub = Math.abs(intTranslationX);
221+
onEnd: (e, ctx: any) => {
222+
if (ctx.lock) {
223+
return;
224+
}
225+
const translationX = ctx.translationX;
235226

236227
function _withTimingCallback(num: number) {
237-
return _withTiming(num, callComputedIndex);
228+
ctx.lock = true;
229+
return withTiming(num, timingConfig, (isFinished) => {
230+
if (isFinished) {
231+
ctx.lock = false;
232+
}
233+
runOnJS(callComputedIndex)(isFinished);
234+
});
238235
}
239236

240-
if (intTranslationX > 0) {
237+
if (translationX > 0) {
238+
/**
239+
* If not loop no , longer scroll when sliding to the start.
240+
* */
241241
if (!loop && handlerOffsetX.value >= 0) {
242242
return;
243243
}
244244

245-
if (sub > width / 2) {
245+
if (
246+
Math.abs(translationX) + Math.abs(e.velocityX) >
247+
width / 2
248+
) {
246249
handlerOffsetX.value = _withTimingCallback(
247-
fillNum(
248-
width,
249-
handlerOffsetX.value + (width - sub)
250-
)
250+
handlerOffsetX.value + width - translationX
251251
);
252252
} else {
253253
handlerOffsetX.value = _withTimingCallback(
254-
fillNum(width, handlerOffsetX.value - sub)
254+
handlerOffsetX.value - translationX
255255
);
256256
}
257257
return;
258258
}
259259

260-
if (intTranslationX < 0) {
260+
if (translationX < 0) {
261+
/**
262+
* If not loop , no longer scroll when sliding to the end.
263+
* */
261264
if (
262265
!loop &&
263266
handlerOffsetX.value <= -(data.length - 1) * width
264267
) {
265268
return;
266269
}
267270

268-
if (sub > width / 2) {
271+
if (
272+
Math.abs(translationX) + Math.abs(e.velocityX) >
273+
width / 2
274+
) {
269275
handlerOffsetX.value = _withTimingCallback(
270-
fillNum(
271-
width,
272-
handlerOffsetX.value - (width - sub)
273-
)
276+
handlerOffsetX.value - width - translationX
274277
);
275278
} else {
276279
handlerOffsetX.value = _withTimingCallback(
277-
fillNum(width, handlerOffsetX.value + sub)
280+
handlerOffsetX.value - translationX
278281
);
279282
}
280283
return;

src/useCarouselController.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
2-
import { _withTiming } from './Carousel';
2+
import { timingConfig } from './Carousel';
33
import type Animated from 'react-native-reanimated';
4-
import { useSharedValue } from 'react-native-reanimated';
4+
import { useSharedValue, withTiming } from 'react-native-reanimated';
55

66
interface IOpts {
77
width: number;
@@ -35,8 +35,9 @@ export function useCarouselController(opts: IOpts): ICarouselController {
3535
if (disable) return;
3636
if (lock.value) return;
3737
openLock();
38-
handlerOffsetX.value = _withTiming(
38+
handlerOffsetX.value = withTiming(
3939
handlerOffsetX.value - width,
40+
timingConfig,
4041
(isFinished: boolean) => {
4142
callback?.(isFinished);
4243
closeLock(isFinished);
@@ -51,8 +52,9 @@ export function useCarouselController(opts: IOpts): ICarouselController {
5152
if (disable) return;
5253
if (lock.value) return;
5354
openLock();
54-
handlerOffsetX.value = _withTiming(
55+
handlerOffsetX.value = withTiming(
5556
handlerOffsetX.value + width,
57+
timingConfig,
5658
(isFinished: boolean) => {
5759
callback?.(isFinished);
5860
closeLock(isFinished);

0 commit comments

Comments
 (0)