Video component from expo-av
is deprecated in favor of expo-video
.
On the other hand, mounting multiple VideoView components (from expo-video
) at the same time with the same VideoPlayer instance does not work due to an Android platform limitation.
Given that, what's the recommended approach for rendering VideoCard components within a FlatList, where each VideoCard includes a VideoView?
This is described as an Android platform limitation, yet expo-av
appears to support it. Could you clarify this discrepancy?
Are you familiar with a fix in the next Expo SDK release?
Home Screen
<FlatList
data={videoItems}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <VideoCard videoItem={item} />}
...
/>
VideoCard Component (example code)
import { useEvent } from 'expo';
import { useVideoPlayer, VideoView } from 'expo-video';
import { StyleSheet, View, Button } from 'react-native';
const VideoCard = ({
videoItem: { creator, videoUrl }
}) => {
const player = useVideoPlayer(videoUrl, player => {
player.loop = false;
player.play();
});
const { isPlaying } = useEvent(player, 'playingChange', { isPlaying: player.playing });
...
return (
<View style={styles.contentContainer}>
<VideoView
style={styles.video}
player={player}
allowsFullscreen={false}
allowsPictureInPicture={false}
/>
...
</View>
);
}
Video component from expo-av
is deprecated in favor of expo-video
.
On the other hand, mounting multiple VideoView components (from expo-video
) at the same time with the same VideoPlayer instance does not work due to an Android platform limitation.
Given that, what's the recommended approach for rendering VideoCard components within a FlatList, where each VideoCard includes a VideoView?
This is described as an Android platform limitation, yet expo-av
appears to support it. Could you clarify this discrepancy?
Are you familiar with a fix in the next Expo SDK release?
Home Screen
<FlatList
data={videoItems}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <VideoCard videoItem={item} />}
...
/>
VideoCard Component (example code)
import { useEvent } from 'expo';
import { useVideoPlayer, VideoView } from 'expo-video';
import { StyleSheet, View, Button } from 'react-native';
const VideoCard = ({
videoItem: { creator, videoUrl }
}) => {
const player = useVideoPlayer(videoUrl, player => {
player.loop = false;
player.play();
});
const { isPlaying } = useEvent(player, 'playingChange', { isPlaying: player.playing });
...
return (
<View style={styles.contentContainer}>
<VideoView
style={styles.video}
player={player}
allowsFullscreen={false}
allowsPictureInPicture={false}
/>
...
</View>
);
}
Share
Improve this question
asked yesterday
NirNir
1132 silver badges6 bronze badges
1 Answer
Reset to default 0Here is the one approach where you can use
Single VideoPlayer: Create one VideoPlayer in the parent compnent.
Single VideoView: Render one VideoView and update its source (videoUrl) using Flatlist’s onViewableItemsChanged.
Placeholder in VideoCard: Show a thumnail in each VideoCard instead of a VideoView.
// State and player setup
const [currentVideoUrl, setCurrentVideoUrl] = useState(videoItems[0]?.videoUrl);
const player = useVideoPlayer(currentVideoUrl, (player) => {
player.loop = false;
player.play();
});
// Detect visible item in FlatList
const viewabilityConfig = { itemVisiblePercentThreshold: 50 };
const onViewableItemsChanged = useRef(({ viewableItems }) => {
if (viewableItems.length > 0) {
const visibleItem = viewableItems[0].item;
if (visibleItem.videoUrl !== currentVideoUrl) {
setCurrentVideoUrl(visibleItem.videoUrl);
player.source = { uri: visibleItem.videoUrl }; // Update video source
player.play();
}
}
});
// Render the VideoView and FlatList
return (
<View>
<VideoView
style={{ width: '100%', height: 200 }}
player={player}
allowsFullscreen={false}
allowsPictureInPicture={false}
/>
<FlatList
data={videoItems}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<VideoCard videoItem={item} isPlaying={item.videoUrl === currentVideoUrl} />
)}
onViewableItemsChanged={onViewableItemsChanged.current}
viewabilityConfig={viewabilityConfig}
/>
</View>
);