Pause video when out of screen view in RecyclerListView in react native

1.4k views Asked by At

I am implementing video playing app(like Instagram Reels or tik tok) using RecyclerListView in React-Native. In the development of app, I am facing the problem that all the videos in the list play simultaneously. I want to pause all other videos which are out of the screen and play only when scrolled to a particular video and video is visible on screen.

How to do it? I have tried a lot of things but could not find solution for RecyclerListView.

I have used react-native-video for playing video.

App.js

import VideoPlayer from './ViewVideo';
const fakeData = [
  {
    type: 'NORMAL',
    item: {
      uri: require('./images/likd2.mp4'),
    },
  },
  {
    type: 'NORMAL',
    item: {
      uri: require('./images/Linkd.mp4'),
    },
  },
  {
    type: 'NORMAL',
    item: {
      uri: require('./images/PlayDate.mp4'),
    },
  },
];
export default class Myworld extends React.Component {
  dataProvider = new DataProvider((r1, r2) => {
    return r1 !== r2;
  }).cloneWithRows(fakeData);

  layoutProvider = new LayoutProvider(
    (i) => {
      return this.dataProvider.getDataForIndex(i).type;
    },
    (type, dim) => {
      switch (type) {
        case 'NORMAL':
          dim.width = '100%';
          dim.height = '100%';
          break;
        default:
          dim.width = '100%';
          dim.height = '100%';
          break;
      }
    },
  );

  rowRenderer = (type, data, index) => {
    switch (type) {
      case 'NORMAL':
        return (
          <View>
            <VideoPlayer source={uri} />
          </View>
        );
    }
  };

  render() {
    return (
      <>
        <SafeAreaView style={styles.container}>
          <RecyclerListView
            style={styles.videolistcontainer}
            rowRenderer={this.rowRenderer}
            dataProvider={this.dataProvider}
            layoutProvider={this.layoutProvider}
            initialOffset={1}
            pagingEnabled={true}
            showsVerticalScrollIndicator={false}
          />
        </SafeAreaView>
      </>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    backgroundColor: '#14171A',
  },
});

ViewVideo.js

const VideoPlayer = (props) => {
  const [paused, setPause] = useState(false);
  return (
    <>
      <TouchableOpacity
        style={{height: height, width: width}}
        onPress={() => setPause(!paused)}>
        <Video
          ref={(ref) => {
            setVideoRef(ref);
          }}
          source={props.source}
          style={styles.backgroundVideo}
          resizeMode={'cover'}
          onError={onError(videoRef)}
          paused={paused}
          onLoad={onLoad}
          onProgress={onProgress}
          onEnd={onEnd}
          repeat={false}
          rate={1.0}
          volume={1.0}
          muted={false}
          onLayout={onVideoLayout}
        />
      </TouchableOpacity>
    </>
  );
};

export default VideoPlayer;
const styles = StyleSheet.create({
  backgroundVideo: {
    position: 'absolute',
    width: WP('100%'),
    height: HP('100%'),
    left: 0,
    right: 0,
    top: 0,
    bottom: 0,
  },
});

1

There are 1 answers

1
Aroldo Goulart On

You can use AppState of React-Native.

It indicate the future state of app: active, background or inactive(IOS only)

Example:

import React, { useRef, useState, useEffect } from "react";
import { AppState, Text, View } from "react-native";
    
const AppInactiveHandleExample = () => {
    const appState = useRef(AppState.currentState);
    const [appStateVisible, setAppStateVisible] = useState(appState.current);

    useEffect(() => {
        AppState.addEventListener("change", handleAppStateChange);
        // Return for clear the cache of action
        return () => {
            AppState.removeEventListener("change", handleAppStateChange);
        };
    }, []);

    const handleAppStateChange = nextAppState => {
    if (
        appState.current.match(/inactive|background/) &&
        nextAppState === "active"
    ) {
        // Execute here your action  
        onAppInactive()
    }
        appState.current = nextAppState;
        setAppStateVisible(appState.current);
    };

    // Action executed when app was inactive or background
    const onAppInactive = () => {
        // Your code here 
    }

    return (
    <View>
        <Text>Current state is: {appStateVisible}</Text>
    </View>
    );
};

export default AppInactiveHandleExample;

https://reactnative.dev/docs/appstate