3
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.

sandeysh
  • 61
  • 1
  • 6

2 Answers2

1

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.

Marek Lisik
  • 2,003
  • 1
  • 8
  • 17
  • Thanks it works...I have two doubts .Whats the use of SafeAreaView? The last video is not playing even when I scroll it to bottom. – sandeysh Apr 13 '21 at 13:17
  • I used `SafeAreaView` out of habit - it just adds a bit of padding for devices that have special areas on screen edges that might obscure content (a camera notch, home indicator on new iPhones). – Marek Lisik Apr 13 '21 at 16:55
  • As for the last video not playing - YouTube's implementation has the same issue. If you want to fix it, you might add a footer to the list that has enough height to push the last item up towards the top edge of the screen. – Marek Lisik Apr 13 '21 at 16:58
0

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>
   )
  }
}