0

I have developed react-native cli, react-native-video (Currently, tried to expo-video).

In a screen, there are one flatList, it has a renderItem(column2). In a renderItem renders image or video thumbnail. Like shopping app UI AMAZON.

The problem is videos. It will stops automatically by user's swipe down to phone's view. Simultaneously, below stopped video, other video player will stops. This video is in exactly middle of user's phone view!

How can i solve this?

  1. FlatList,

const [videoPlayback, setVideoPlayback] = useState(false);
 const viewabilityConfig = {
    itemVisiblePercentThreshold: 80,
  };

  const _onViewableItemsChanged = useCallback((props) => {
    const changed = props.changed;
    changed.forEach((item) => {
      if (item.item.vimeoId) {
        if (item.isViewable) {
          setVideoPlayback((prev) => true);
        } else {
          setVideoPlayback((prev) => false);
        }
      }
    });
  }, []);
...
      <FlatList
        ref={ref}
        numColumns={2}
        data={posts}
        keyExtractor={(item: any) => `${item.postId}`}
        viewabilityConfig={viewabilityConfig}
        onViewableItemsChanged={_onViewableItemsChanged}
        renderItem={({ item, index }) => (
          <PostContainer item={item} videoPlayback={videoPlayback} navigation={navigation} index={index} />
        )}

  1. PostContainer
const PostContainer = ({ item, videoPlayback }) => {
  const videoPlayer = useRef(null);

  useFocusEffect(
    React.useCallback(() => {
      videoPlayer?.current?.seek(0);

      if (videoPlayer && !videoPlayback) {
        videoPlayer?.current?.seek(0);
      }
    }, [fadeAnim, videoPlayback]),
  );

  return (
    <View>

      { // This place that image component rendered}

      {item.vimeoId && (
        <StyledVideo
          ref={videoPlayer}
          paused={!videoPlayback}
          repeat={true}
          resizeMode={"cover"}
          volume={0}
          source={{
            uri: item.vimeoThumbnail,
          }}
        />
      )}
    </View>
  );
};

rudenick
  • 154
  • 1
  • 1
  • 10

2 Answers2

0

All the videos in your list share the same videoPlayback state. If you want each video to be controlled individually, move your videoPlayback state logic into your PostContainer.

Krismu
  • 503
  • 4
  • 14
  • I have tried to apply your answer in my code. But, I cannot solve problem. By writing "const [playing, setPlaying] = React.useState(false);" at PostContainer. "" if (videoPlayer && !videoPlayback) { setPlaying((prev) => true); videoPlayer?.current?.seek(0); } "". And StyledVideo component, I had changed "paused={!videoPlayback}" to "paused={!playing}" – rudenick Sep 28 '21 at 00:45
  • As I look at it, "if (videoPlayer && !videoPlayback)" this condition is fault. Do you have any opinions on this? – rudenick Sep 28 '21 at 00:46
0

I solved my problem. There are no fault in my logic. the important thing is 'What videos are current playing?'

  1. FlatList
  const _onViewableItemsChanged = useCallback(
    (props) => {
      const changed = props.changed;
      changed.forEach((item) => {
        if (item.item.vimeoId) {
          const tempId = item.item.vimeoId;

          if (item.isViewable) {
            if (readVideosVar.list.indexOf(tempId) === -1) {
              dispatch(postSlice.actions.addId(tempId));
            }
          } else {
            dispatch(postSlice.actions.deleteId(tempId));
          }
        }
      });
    },
    [dispatch],
  );
  1. redux
    addId: (state, action) => {
      if (state.list.indexOf(action.payload) !== -1) {
        return;
      } else {
        let tempA = [];
        tempA.push(action.payload);
        state.list = state.list.concat(tempA);
      }
    },
    deleteId: (state, action) => {
      if (state.list.indexOf(action.payload) === -1) {
        return;
      } else {
        let stand = state.list;
        let findIdx = stand.indexOf(action.payload);
        let leftA = stand.slice(0, findIdx);
        let rightA = stand.slice(findIdx + 1);
        state.list = leftA.concat(rightA);
      }
    },

Compared to the existing code, I had added 'redux-toolkit'. In dispatch logic, "onViewalbeItems" had tracked chagend viewable items by real-time.

And then, I also added,

export const viewabilityConfig = {
  minimumViewTime: 1000,
  viewAreaCoveragePercentThreshold: 0,
};

This is just sugar.

I solved it like this !

rudenick
  • 154
  • 1
  • 1
  • 10