Autoplay video on element focus in react-native

Viewed 1957
import {Video} from 'expo-av';
return (

      <FlatList 
        data={videos}
        // keyExtractor={(item,ind}
        keyExtractor={(item) => item.names}
        renderItem={({item})=>(
          <TouchableOpacity
          onPress={() => {console.log('pushed');navigation.push('Details',{url:item.videourl})}}>
            <Video
                usePoster="true"
                source={{ uri: item.videourl }}
                rate={1.0}
                volume={1.0}
                isMuted={false}
                resizeMode="cover"
                shouldPlay={isFocused ? true : false}
                // isLooping
                // useNativeControls
                posterSource={{uri:item.imageurl}}
                style={{ height: 300 }}
                
                
                /> 
                


          </TouchableOpacity>
        )}/>

  );

If one video gets focused then the video must be played and if the video is not focused then it should pause.I am using expo-av for playing video. The above code is playing all videos on the screen but I want to play the video which is focused just like what youtube does.

2 Answers

To do this you need to keep track of how the scrollview has moved (the offset). FlatList has an onScroll property, where the callback is given information about the list layout etc., and you are interested in tracking how much the content has been scrolled vertically - that is contentOffset.y.

Dividing this value by the list item height (a constant 300 in your case) and rounding will give you the index of the item that should be playing.

Use state to store the currently focused index:

const [focusedIndex, setFocusedIndex] = React.useState(0);

Add a handler for the onScroll event :

const handleScroll = React.useCallback(({ nativeEvent: { contentOffset: { y } } }: NativeSyntheticEvent<NativeScrollEvent>) => {
  const offset = Math.round(y / ITEM_HEIGHT);

  setFocusedIndex(offset)
}, [setFocusedIndex]);

Pass the handler to your list:

<FlatList
  onScroll={handleScroll}
  ...
/>

and modify the video's shouldPlay prop:

<Video
  shouldPlay={focusedIndex === index}
  ...
/>

You can see a working snack here: https://snack.expo.io/@mlisik/video-autoplay-in-a-list, but note that the onScroll doesn't seem to be called if you view the web version.

Try https://github.com/SvanBoxel/visibility-sensor-react-native

Saved my time. You can use it like.

import VisibilitySensor from '@svanboxel/visibility-sensor-react-native'

const Example = props => {
  const handleImageVisibility = visible = {
    // handle visibility change
  }

  render() {
    return (
      <View style={styles.container}>
        <VisibilitySensor onChange={handleImageVisibility}>
          <Image
            style={styles.image}
            source={require("../assets/placeholder.png")}
           />
         </VisibilitySensor>
    </View>
   )
  }
}
Related