react-native-media-console icon indicating copy to clipboard operation
react-native-media-console copied to clipboard

Feature: Gesture Handling Enhancement for use with FlatList

Open coofzilla opened this issue 1 year ago • 5 comments

Problem

When embedding the VideoPlayer component within a horizontally scrolling FlatList, there is a gesture conflict that arises. Specifically, when attempting to seek in the video (or volume) by dragging the seeker control left or right, the FlatList interprets this gesture as a horizontal scroll, leading to an unintended navigation away from the current video item instead of seeking within the video.

Expected Behavior

The expected behavior is that when interacting with the video player's seeking controls, the FlatList scrolling should be temporarily disabled or the gesture should be captured exclusively by the video player, allowing for a smooth seeking experience without triggering a scroll in the FlatList.

Current Workaround

Still trying to figure this out 😅

Example Snippet

Here is a simplified code snippet demonstrating the setup:

<FlatList
  data={videos}
  horizontal
  renderItem={({ item }) => (
    <View>
      <VideoPlayer
        source={{ uri: item.url }}
        // Other necessary props
      />
    </View>
  )}
/>

coofzilla avatar Apr 02 '24 02:04 coofzilla

@coofzilla Indeed, this is an ugly one... Not sure if I can find a good fix, but perhaps we can workaround it. I'm still looking into it. Will let you know if I find something useful.

Related: https://github.com/facebook/react-native/issues/28135

LunatiqueCoder avatar Aug 10 '24 12:08 LunatiqueCoder

@coofzilla What do you think about the following fix? The parentListRef would accept either FlatList or Scrollview refs. Internally, it would call parentListRef?.current?.setNativeProps({scrollEnabled: boolean}); in order to avoid this issue.

export const VideoList = () => {
  const flatListRef = useRef<FlatList>(null);

  return (
      <FlatList
        ref={flatListRef}
        data={videos}
        horizontal
        renderItem={({ item }) => (
          <View>
            <VideoPlayer
              parentListRef={flatListRef}
              source={{ uri: item.url }}
              // Other necessary props
            />
          </View>
        )}
      />
   )
}

The issue with this approach is that if the developers are using scrollEnabled prop with useState, it might interfere with this workaround and lead to unexpected behaviour and issues. More info here: https://reactnative.dev/docs/direct-manipulation

LunatiqueCoder avatar Aug 10 '24 14:08 LunatiqueCoder

Looks good to me, especially since you've documented the change—this will give developers a clear example to follow when implementing it.

Just to clarify, would this approach work the same way for VideoPlayers inside FlatLists or ScrollViews that are vertical? Essentially, the same snippet you provided, but without horizontal.

coofzilla avatar Aug 11 '24 03:08 coofzilla

Just to clarify, would this approach work the same way for VideoPlayers inside FlatLists or ScrollViews that are vertical? Essentially, the same snippet you provided, but without horizontal.

@coofzilla Yes, I think so. I will update the PR today and you'll be able to test it in ./examples/MyTVProject. If you confirm everything works fine, I'll merge and release a new version with the fix.

LunatiqueCoder avatar Aug 12 '24 06:08 LunatiqueCoder

@coofzilla The branch is updated. The final implementation is like this:

export const VideoList = () => {
  const flatListRef = useRef<FlatList>(null);
  const [scrollEnabled, setScrollEnabled] = useState<boolean>(true)

  return (
      <FlatList
        ref={flatListRef}
        scrollEnabled={scrollEnabled}
        data={videos}
        horizontal
        renderItem={({ item }) => (
          <View>
              <VideoPlayer
                pan={{
                  parentList: {
                    ref: flatListRef,
                    scrollEnabled: scrollEnabled, // This is optional and only needed if `scrollEnabled` prop is used with FlatList
                  },
                }}
                source={{uri: 'https://vjs.zencdn.net/v/oceans.mp4'}}
              />
          </View>
        )}
      />
   )
}

You can test those changes in ./examples/MyTVProject. See https://github.com/LunatiqueCoder/react-native-media-console/blob/master/CONTRIBUTING.md

Let me know if this fixes your issues

LunatiqueCoder avatar Aug 12 '24 06:08 LunatiqueCoder

@LunatiqueCoder i am not able to find this code, can you please help me to figure that out

yash-prolytech avatar Nov 04 '25 12:11 yash-prolytech