实现思路: 视频播放采用react-native-video,非常好用的视频播放库,列表整体采用FlatList实现,每一个item都占一整屏(flex设为1),再给FlatList设定pagingEnabled属性(滑动滚动一屏),viewabilityConfig中设定可见区域滑动的阈值。
效果图:
实现过程:
我的代码使用了react-native-ui-lib库,所以直接复制控件的属性会报错,把写在标签里的style样式写进对应控件的style={{}}中。
react-native-video的具体导入和使用方法 就自己去github看一下把,文档说明非常详细
constructor(props){ super(props) this.state={ data:tempCollect,//我模拟的数据 这个就自行找一些视频url就好 isPause:true, //控制播放器是否播放,下面的代码有解释一个列表只需要一个state控制,而不用数组 current:0,//表示当前item的索引,通过这个实现一个state控制全部的播放器 } this.renderItem = this.renderItem.bind(this) this._onViewableItemsChanged = this._onViewableItemsChanged.bind(this) }render方法代码:
render(){ const VIEWABILITY_CONFIG = { viewAreaCoveragePercentThreshold: 80,//item滑动80%部分才会到下一个 }; return( <View> <FlatList data={videoUrl} renderItem={this.renderItem} horizontal={false} pagingEnabled={true} getItemLayout={(data, index) => { return {length: height, offset: height * index, index} }} keyExtractor={(item, index) => index.toString()} viewabilityConfig={VIEWABILITY_CONFIG} showsHorizontalScrollIndicator={false} onViewableItemsChanged={this._onViewableItemsChanged} /> {/*顶部 关闭、搜索 按钮*/} <View style={{position:'absolute',width:width,}}> <View row style={{justifyContent: 'space-between',alignItems: 'center',width:width,padding:20}} > <TouchableOpacity onPress={()=>{ this.props.navigation.goBack(); }}> <Image source={require('../../res/img/shootVideo/close.png')} style={{width:30,height:30}} /> </TouchableOpacity> <TouchableOpacity > <Image source={require('../../res/img/shootVideo/search.png')} style={{width:30,height:30}} /> </TouchableOpacity> </View> </View> </View> ) } _onViewableItemsChanged({viewableItems, changed}) { //这个方法为了让state对应当前呈现在页面上的item的播放器的state //也就是只会有一个播放器播放,而不会每个item都播放 //可以理解为,只要不是当前再页面上的item 它的状态就应该暂停 //只有100%呈现再页面上的item(只会有一个)它的播放器是播放状态 if(viewableItems.length === 1){ this.setState({ current:viewableItems[0].index, }) } }FlatList中renderItem布局代码:
/** item布局 播放器 等*/ renderItem({item,index}){ return( <View style={{width:width,height:height-STATUSBAR_HEIGHT}}> <TouchableWithoutFeedback style={{flex:1}} onPress={()=>{ this.setState({ isPause:!this.state.isPause, }) }}> <Video source={{uri:item}} style={{flex: 1,backgroundColor:'#000'}} repeat={true} paused={index===this.state.current?this.state.isPause:true} resizeMode='contain' > </Video> </TouchableWithoutFeedback> {/*信息(头像,标题等)、写评论*/} <View column style={{position:'absolute',width:width,height:height-STATUSBAR_HEIGHT,justifyContent:'flex-end',padding: 20,marginBottom:30}}> <View row style={{alignItems:'center'}}> <Image source={require('../../res/img/shootVideo/user_icon.png')} style={{width:50,height:50,borderRadius:50,}} /> <Text style={{fontSize:15,color:'#fff',marginLeft:10}}>懒散少女和猫</Text> <TouchableOpacity center style={{width:60,height:30,backgroundColor:'#f98589',borderRadius:5,marginLeft:10}}> <Text style={{fontSize:14,color:'#fff'}}>关注</Text> </TouchableOpacity> </View> <Text style={{fontSize:14,color:'#fff',marginTop:10}}>美丽的傍晚</Text> <View style={{flexDirection:'row',alignItems:'center',backgroundColor:'rgba(0,0,0,0.5)',borderRadius:5,padding:3,width:155,marginTop:10}}> <Image source={require('../../res/img/shootVideo/bgmusic.png')} style={{width:15,height:15}} /> <Text style={{fontSize:13,color:'#fff',marginLeft:10}}>@懒散的少女和猫</Text> </View> <View style={{marginTop:10}}> <TouchableOpacity row style={{backgroundColor:'#4d4d4d',borderRadius:17,padding:10,alignItems:'center',width:270}}> <Image source={require('../../res/img/shootVideo/write_review.png')} style={{width:15,height:15}} /> <Text style={{fontSize:14,color:'#fff',marginLeft:10}}>写评论...</Text> </TouchableOpacity> </View> </View> {/*底部 右侧 功能键 (我拍,点赞,评论,转发)*/} <View column style={{position:'absolute',width:width,height:height-STATUSBAR_HEIGHT,justifyContent:'flex-end',alignItems:'flex-end',padding: 20}}> <TouchableOpacity column center style={styles.bottomRightBn} > <Image source={require('../../res/img/shootVideo/shoot.png')} resizeMode={'contain'} style={styles.bottomRightImage}/> <Text style={styles.bottomRightText}>我拍</Text> </TouchableOpacity> <TouchableOpacity column center style={styles.bottomRightBn}> <Image source={require('../../res/img/shootVideo/like.png')} resizeMode={'contain'} style={styles.bottomRightImage}/> <Text style={styles.bottomRightText}>2.1万</Text> </TouchableOpacity> <TouchableOpacity column center style={styles.bottomRightBn}> <Image source={require('../../res/img/shootVideo/review.png')} resizeMode={'contain'} style={styles.bottomRightImage}/> <Text style={styles.bottomRightText}>300</Text> </TouchableOpacity> <TouchableOpacity column center style={[styles.bottomRightBn,{marginBottom:50}]}> <Image source={require('../../res/img/shootVideo/share.png')} resizeMode={'contain'} style={styles.bottomRightImage}/> <Text style={styles.bottomRightText}>分享</Text> </TouchableOpacity> </View> {/* 屏幕中央 播放按钮 */} { this.state.isPause? <View column center flex style={{position:'absolute',width:width,height:height-STATUSBAR_HEIGHT,}}> <TouchableOpacity onPress={()=>{this.setState({ isPause:!this.state.isPause, })}} > <Image source={require('../../res/img/shootVideo/play.png')} resizeMode={'contain'} style={{width:60,height:60}} /> </TouchableOpacity> </View>:null } </View> ) }代码中用到的样式:
const styles = StyleSheet.create({ container: { flex: 1, }, center: { justifyContent: 'center', alignItems: 'center', }, bottomRightBn:{ width:50, height:50, marginTop:20, }, bottomRightImage:{ width:30, height:30, }, bottomRightText:{ fontSize:14, color:'#fff', marginTop:5, } });