Friday 15 December 2023

React Native Touch Through Flatlist

For "react-native": "^0.70.5"

Requirement:

  • Flatlist as an overlay above Clickable elements
  • Flatlist header has a transparent area, with pointerEvents="none" to make the elements below clickable and yet allow the Flatlist to scroll. enter image description here

Issues with some possible approaches

  1. pointerEvents="none" doesn't work with Flatlist, as internally how Flatlist is built it will block the events at all values of pointerEvents. It's the same with Scrollview as well.
  2. react-native-touch-through-view (the exact library I need) doesn't work with RN 0.70.2, library is outdated. After fixing the build issues, touch events are not propagating to the clickable elements.
  3. Created a custom component ScrollableView, as pointerEvents with View work well. With this adding pointerEvents to none on parts of the children, lets the touch event to propagate to elements below.
  • This is working well on Android, but failing on iOS.
  • Also the scrolling of the view is not smooth.
  • Requires further handling for performance optimisation for long lists
import React, { useState, useRef } from 'react';
import { View, PanResponder, Animated } from 'react-native';

const ScrollableView = ({children, style, onScroll}) => {
    const scrollY = useRef(new Animated.Value(0)).current;
    const lastScrollY = useRef(0);
    const scrollYClamped = Animated.diffClamp(scrollY, 0, 1000);

    const panResponder = useRef(
        PanResponder.create({
            onStartShouldSetPanResponder: () => true,
            onPanResponderMove: (_, gestureState) => {
                scrollY.setValue(lastScrollY.current + gestureState.dy);
            },
            onPanResponderRelease: (_, { vy, dy }) => {
                lastScrollY.current += dy;
                Animated.spring(scrollY, {
                    toValue: lastScrollY.current,
                    velocity: vy,
                    tension: 2,
                    friction: 8,
                    useNativeDriver: false,
                }).start();
            },

        })
    ).current;

    const combinedStyle = [
        {
            transform: [{ translateY: scrollYClamped }],
        },
        style
    ];

    return (
        <Animated.View
            {...panResponder.panHandlers}
            pointerEvents="box-none"
            style={combinedStyle}
        >
            {children}
        </Animated.View>
    );
};

export default ScrollableView;

Any solution to any of the above three approaches is appreciated.



from React Native Touch Through Flatlist

No comments:

Post a Comment