Topic:React Native中的视频平面列表。 (普通视频/ YouTube视频)
根据阵列数据将同时显示任何一个。因此,它将是一个包含两种类型视频的长列表。
有时由于性能问题,许多onPress事件不起作用
主要问题:
以上两个是需要解决的主要问题。有什么方法可以解决这些问题?
我可以尝试哪些解决方案来提高Flatlist
性能并解决视频平板列表崩溃问题?
下面是我在App.js中的代码]
import React from "react"; import { StyleSheet, Text, View, SafeAreaView, FlatList, TouchableWithoutFeedback, Dimensions } from "react-native"; import Video from "react-native-video"; import ProgressBar from "react-native-progress/Bar"; import YouTube from 'react-native-youtube'; import LightVideo from "./sample.mp4"; import Icon from "react-native-vector-icons/FontAwesome"; // console.disableYellowBox = true; function secondsToTime(time) { return ~~(time / 60) + ":" + (time % 60 < 10 ? "0" : "") + time % 60; } const { width } = Dimensions.get("window"); const height = width * 0.5625; const list = [ { 'type': 'YouTube' }, { 'type': 'Normal' }, { 'type': 'YouTube' }, { 'type': 'Normal' }, { 'type': 'Normal' }, ]; export default class RNVideo extends React.PureComponent { state = { video: [], duration: [0, 0, 0, 0, 0], progress: [0, 0, 0, 0, 0] }; constructor(props) { super(props); this.player = []; } componentDidMount() { this.progress_state(); this.duration_state(); this.video_pause_state(false); } play_pause_button = (index) => { if (this.state.progress >= 1) { this.player[index].seek(0); } var statevisible = this.state.video; statevisible[index] = !statevisible[index]; this.setState({ video: statevisible }); this.forceUpdate(); }; progress_bar_touch(e, index) { const position = e.nativeEvent.locationX; const progress = (position / 250) * this.state.duration[index]; this.player[index].seek(progress); }; handleProgress(progress, index) { var statevisible = this.state.progress; statevisible[index] = progress.currentTime / this.state.duration[index]; this.setState({ progress: statevisible }); this.forceUpdate(); }; handleLoad(meta, index) { var statevisible = this.state.duration; statevisible[index] = meta.duration; this.setState({ duration: statevisible }); this.forceUpdate(); }; onViewableItemsChanged = async ({ viewableItems }) => { this.video_pause_state(true); if (viewableItems != '' && viewableItems != null) { var indexvalue = viewableItems[0]['index']; var statevisible = this.state.video; statevisible[indexvalue] = !statevisible[indexvalue]; this.setState({ video: statevisible }); this.forceUpdate(); } } // shouldComponentUpdate() { // return false // } video_pause_state(value) { var statevisible = []; for (var i = 0; i < list.length; i++) { statevisible[i] = value; } this.setState({ video: statevisible }); } progress_state() { var statevisible = []; for (var i = 0; i < list.length; i++) { statevisible[i] = 0; } this.setState({ progress: statevisible }); } duration_state() { var statevisible = []; for (var i = 0; i < list.length; i++) { statevisible[i] = 0; } this.setState({ duration: statevisible }); } video_end(index) { var statevisible1 = this.state.duration; statevisible1[index] = 0; var statevisible2 = this.state.progress; statevisible2[index] = 0; this.setState({ duration: statevisible1, progress: statevisible2 }); this.play_pause_button(index); } keyExtractor = (item, index) => index.toString() renderItem = ({ item, index }) => ( <> {item.type != 'YouTube' ? <> <View style={styles.container}> <View> <Video paused={this.state.video[index]} muted={this.state.video[index]} source={LightVideo} // controls={true} // repeat={true} style={styles.videos} resizeMode="cover" onLoad={(meta) => this.handleLoad(meta, index)} onProgress={(progress) => this.handleProgress(progress, index)} onEnd={() => this.video_end(index)} ref={(ref) => { this.player[index] = ref }} /> <View style={styles.controls}> <TouchableWithoutFeedback onPress={(event) => this.play_pause_button(index)}> <Icon name={!this.state.video[index] ? "pause" : "play"} size={30} color="#FFF" /> </TouchableWithoutFeedback> <TouchableWithoutFeedback onPress={(event) => this.progress_bar_touch(event, index, this)}> <View> <ProgressBar progress={this.state.progress[index]} color="#FFF" unfilledColor="rgba(255,255,255,.5)" borderColor="#FFF" width={230} height={20} /> </View> </TouchableWithoutFeedback> <Text style={styles.duration}> {secondsToTime(Math.floor(this.state.progress[index] * this.state.duration[index]))} </Text> </View> </View> </View> </> : <> <View style={{ marginTop: 50 }}> <YouTube apiKey="YOUR_API_KEY" videoId="YOUR_YOUTUBE_VIDEO_ID_FROM_URL" play={this.state.video[index]} style={styles.videos} /> </View> </> } </> ) render() { return ( <> <SafeAreaView style={{ flex: 1 }}> <FlatList keyExtractor={this.keyExtractor} data={list} renderItem={this.renderItem} extraData={this.state} onViewableItemsChanged={this.onViewableItemsChanged} removeClippedSubviews={true} maxToRenderPerBatch={3} initialNumToRender={3} legacyImplementation={true} /> </SafeAreaView> </> ); } } const wid = "95%"; const styles = StyleSheet.create({ container: { flex: 1, marginBottom: 60, marginTop: 60, }, controls: { backgroundColor: "rgba(0, 0, 0, 0.5)", height: 48, left: 0, bottom: 0, right: 0, position: "absolute", flexDirection: "row", alignItems: "center", justifyContent: "space-around", width: wid, margin: 8, borderBottomLeftRadius: 10, borderBottomRightRadius: 10, paddingHorizontal: 10, }, mainButton: { marginRight: 15, }, duration: { color: "#FFF", marginLeft: 15, }, videos: { width: wid, backgroundColor: '#ccc', borderRadius: 10, overflow: 'hidden', margin: 8, height }, });
更新
我已经提出了最终解决方案。但无法执行自动播放。需要这个想法。
import React from 'react';
import { View, StyleSheet, SafeAreaView } from 'react-native';
import YouTube from 'react-native-youtube';
import { OptimizedFlatList } from 'react-native-optimized-flatlist'
import VideoPlayer from 'react-native-video-player';
const list = [
{
'type': 'Normal'
},
{
'type': 'YouTube'
},
{
'type': 'Normal'
},
{
'type': 'Normal'
},
{
'type': 'YouTube'
},
{
'type': 'Normal'
},
{
'type': 'Normal'
},
{
'type': 'Normal'
},
];
export default class App extends React.PureComponent {
constructor() {
super();
this.player = [];
this.state = {
video: { width: undefined, height: undefined, duration: undefined },
thumbnailUrl: undefined,
videoUrl: undefined,
};
}
keyExtractor = (item, index) => index.toString()
renderItem = ({ item, index }) => (
<>
{item.type != 'YouTube' ?
<>
<View style={styles.videos}>
<VideoPlayer
// autoplay
// pauseOnPress
video={{ uri: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4', type: 'mp4' }}
resizeMode={'cover'}
ref={r => this.player[index] = r}
/>
</View>
</>
:
<>
<View style={{ marginTop: 50 }}>
<YouTube
apiKey="YOUR_API_KEY"
videoId="3NQRhE772b0"
style={{...styles.videos,...styles.videos1}}
/>
</View>
</>
}
</>
)
onViewableItemsChanged = async ({ viewableItems }) => {
if (viewableItems != '' && viewableItems != null) {
var indexvalue = viewableItems[0]['index'];
indexvalue++;
if (indexvalue != 1) {
if (!this.player[indexvalue].state.isPlaying) {
this.player[indexvalue].pause();
} else {
this.player[indexvalue].resume();
}
}
}
}
render() {
return (
<>
<SafeAreaView style={{ flex: 1 }}>
<OptimizedFlatList
keyExtractor={this.keyExtractor}
data={list}
renderItem={this.renderItem}
removeClippedSubviews={true}
onViewableItemsChanged={this.onViewableItemsChanged}
/>
</SafeAreaView>
</>
);
}
}
const styles = StyleSheet.create({
videos: {
width: "95%",
backgroundColor: '#ccc',
borderRadius: 10,
overflow: 'hidden',
margin: 10,
marginBottom: 20,
marginTop: 20
},
videos1: {
height: 250
}
});
主题:React Native中的视频平面列表。 (普通视频/ YouTube视频)将根据阵列数据同时显示任何一个。因此它将是一个长长的扁平列表,其中包含两种类型的...
我已经提出了最终解决方案。但无法执行自动播放。需要这个想法。请帮助