Performance Lag in Carousel Animations on Real Android Devices Compared to Simulator
defild9 opened this issue · 3 comments
Describe the bug
On a real Android device, animations in the CarouselListItem
component are noticeably slower compared to the Android simulator. This issue manifests as lag during image scrolling, item transitions, and gesture handling. The performance difference is more pronounced on real devices.
To Reproduce
Steps to reproduce the behavior:
-
Implement the following
CarouselListItem
component:const CarouselListItem = ({ item, shareHandler, addToWishlistHandler, removeFromWishlistHandler, stared, }: CarouselItem) => { const [currentImageIndex, setCurrentImageIndex] = React.useState(0); const baseOptions = { vertical: false, width: PAGE_WIDTH * 0.9, height: 232, } as const; const images = item?.lot?.image_urls || []; const isSold = item.lot.is_sold; return images.length > 0 ? ( <CarouselContainer> <Carousel {...baseOptions} data={images} windowSize={3} scrollAnimationDuration={200} onSnapToItem={(index) => setCurrentImageIndex(index)} pagingEnabled={true} onProgressChange={(_, absoluteProgress) => { setCurrentImageIndex(Math.round(absoluteProgress)); }} panGestureHandlerProps={{ activeOffsetX: [-10, 10], }} renderItem={({ item }) => ( <Flexbox> <ImageBackground style={{ flex: 1 }} imageStyle={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }} source={{ uri: item }} > <Flexbox justifyContent={'space-between'} borderRadius={16} height={232}> <Flexbox flexDirection={'column'}> <TouchableOpacity onPress={shareHandler} style={{ padding: 15, backgroundColor: '#0C0C0C80', borderTopLeftRadius: 16, borderBottomRightRadius: 8, }} > <ShareIcon /> </TouchableOpacity> </Flexbox> <Flexbox flexDirection={'column'}> <TouchableOpacity disabled={isSold} onPress={ stared ? removeFromWishlistHandler : addToWishlistHandler ? addToWishlistHandler : () => {} } style={{ padding: 15, backgroundColor: '#0C0C0C80', borderTopRightRadius: 16, borderBottomLeftRadius: 8, }} > {stared ? ( <StarFilledIcon color={'#fff'} /> ) : ( <StarIcon color={isSold ? '#a0a0a0' : '#fff'} /> )} </TouchableOpacity> </Flexbox> </Flexbox> </ImageBackground> </Flexbox> )} /> <Dots passiveDotHeight={8} passiveDotWidth={8} activeDotWidth={12} activeDotHeight={8} length={images.length} active={currentImageIndex} activeColor="#1B6BC8" passiveColor="#E8EBEF" /> </CarouselContainer> ) : ( <TouchableWithoutFeedback> <Flexbox> <ImageBackground style={{ flex: 1 }} imageStyle={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }} source={{ uri: item.lot.image_urls[0] ?? item.lot.thumb }} > <Flexbox justifyContent={'space-between'} borderRadius={16} height={232}> <Flexbox flexDirection={'column'}> <TouchableOpacity onPress={shareHandler} style={{ padding: 15, backgroundColor: '#0C0C0C80', borderTopLeftRadius: 16, borderBottomRightRadius: 8, }} > <ShareIcon /> </TouchableOpacity> </Flexbox> <Flexbox flexDirection={'column'}> <TouchableOpacity disabled={isSold} onPress={ stared ? removeFromWishlistHandler : addToWishlistHandler ? addToWishlistHandler : () => {} } style={{ padding: 15, backgroundColor: '#0C0C0C80', borderTopRightRadius: 16, borderBottomLeftRadius: 8, }} > {stared ? ( <StarFilledIcon color={'#fff'} /> ) : ( <StarIcon color={isSold ? '#a0a0a0' : '#fff'} /> )} </TouchableOpacity> </Flexbox> </Flexbox> </ImageBackground> </Flexbox> </TouchableWithoutFeedback> ); }; export default CarouselListItem;
-
Run the app on both a real Android device and an Android simulator.
-
Scroll through the images in the carousel on both platforms.
-
Observe the difference in animation performance.
Expected behavior
Animations should be smooth and responsive on both real Android devices and Android simulators.
Screenshots
N/A
Versions (please complete the following information):
- react: v18.2.0
- react-native: v0.72.410
- react-native-reanimated: v3.14.0
- react-native-reanimated-carousel: v3.5.1
- react-native-gesture-handler: v2.17.1
Smartphone (please complete the following information):
- Device: Samsung Galaxy S9
- OS: Android 10
- Browser: N/A
- Version: N/A
Additional context
The issue might be related to the processing power differences between simulators and real devices, or it could be due to the configuration of scrollAnimationDuration
, panGestureHandlerProps
, or the complexity of the components within the carousel. Testing on multiple devices and optimizing gesture handling and animations may help resolve this.
Hey there, @defild9! I'm here to help you with any bugs, questions, or contributions you have in mind. Let's squash those bugs together! 🤖
To address the performance lag in the CarouselListItem
component's animations on real Android devices, you can try the following steps:
-
Update the
react-native-reanimated-carousel
Package:
Ensure you are using the latest version of thereact-native-reanimated-carousel
package. The latest patch reduces the amount of work done when rendering data, which should help improve performance [1]. -
Optimize Animation Style:
Use theinterpolate
andExtrapolate
functions fromreact-native-reanimated
to ensure smoother transitions and less computational overhead. Here is an example of how you can define a custom animation style:import { Extrapolate, interpolate } from "react-native-reanimated"; import Carousel, { TAnimationStyle } from "react-native-reanimated-carousel"; const animationStyle: TAnimationStyle = (value: number) => { "worklet"; const itemOffsetInput = new Array(sideItemCount * 2 + 1) .fill(null) .map((_, index) => index - sideItemCount); const itemOffset = interpolate( value, itemOffsetInput, itemOffsetInput.map((item) => { if (item < 0) { return (-itemSize + sideItemWidth) * Math.abs(item); } else if (item > 0) { return (itemSize - sideItemWidth) * (Math.abs(item) - 1); } return 0; }) as number[], ); const translate = interpolate(value, [-1, 0, 1], [-itemSize, 0, itemSize]) + centerOffset - itemOffset; const width = interpolate(value, [-1, 0, 1], [sideItemWidth, itemSize, sideItemWidth], Extrapolate.CLAMP); return { transform: [ { translateX: translate, }, ], width, overflow: "hidden", }; };
-
Adjust
windowSize
andscrollAnimationDuration
Props:
ThewindowSize
prop can be used to control how many items are rendered around the current item. Reducing this number can improve performance. The default value is0
, which means all items will respond to pan gesture events [2]. You can try setting it to a smaller value, such as3
, as you have done in your example.The
scrollAnimationDuration
prop controls the duration of the scroll animation. The default value is500
ms [2]. You can experiment with different values to find the optimal duration for smooth animations. -
Review Similar Issues:
There are similar issues reported in the repository that might provide additional insights:
By following these steps, you should be able to mitigate the performance issues you're experiencing on real Android devices.