使用 Swiper 组件播放暂停问题反应原生多视频

Posted

技术标签:

【中文标题】使用 Swiper 组件播放暂停问题反应原生多视频【英文标题】:react native multiple video with Swiper component play pause issue 【发布时间】:2019-02-23 17:00:54 【问题描述】:

我在滑动器中有多个视频,可以一个一个地显示视频,但是所有视频都同时加载和播放,并且音频混乱,我希望一次只播放当前视频。

import * as React from 'react';
import  Text, View, StyleSheet,Image, Dimensions  from 'react-native';
import  Constants  from 'expo';
import  Video  from 'expo';
import Swiper from './Swiper';
import InViewPort from './InViewport';
const screenWidth = Dimensions.get('window').width ;
const screenHeight = Dimensions.get('window').height;

export default class App extends React.Component 
  constructor(props) 
    super(props);
    // Your source data
    this.state = 
      images: ,
      muted : false,
      paused: true,
    ;
    this.player = Array();
    this.onChangeImage = this.onChangeImage.bind(this);
  

   videoError(err)
     console.warn(err);
   

   pauseVideo = () => 
     var curr = this.state.currentIndex;
     console.warn(curr);
     if(this.player[curr]) 
       this.setState(paused: true );
     
   

   playVideo = () => 
     var curr = this.state.currentIndex;
     console.warn(curr);
     if(this.player[curr]) 
     this.setState(paused: false);
     
   

   handlePlaying = (isVisible) => 
     isVisible ? this.playVideo() : this.pauseVideo();
   


  onChangeImage (index) 
     this.setState( currentIndex: index);
   


  render() 
   let items = Array.apply(null, Array(15)).map((v, i) => 
      return 
        id: i,
        caption: i + 1,
        source:  uri: 'http://placehold.it/200x200?text=' + (i + 1) ,
        dimension: ' width: 150, height: 150 ',
      ;
    );
      return(
        <View style=styles.DefaultView>
          <Swiper
          showsPagination=false
          onIndexChanged=this.onChangeImage
          index=0
          >
           items.map((item, key) => 
             if(key==1 || key ==5)
               return (
                 <InViewPort onChange=this.handlePlaying key=key>
                  <Video onError=this.videoError
                   muted=this.state.muted
                   paused=this.state.paused
                   source=uri: 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4' 
                   style=styles.backgroundVideo
                   ref=(ref) => 
                      this.player[key] = ref;
                    
                    controls=true
                   />
                  </InViewPort>
               )
             else
               return(
                 <Image
                   resizeMode='contain'
                   style=width:screenWidth, height: screenHeight
                   source=item.source
                   key=key
               />
              )
             
           )
         </Swiper>
         </View>
      )
  


const styles = StyleSheet.create(
    scrollView: 
        flex: 1,
        flexDirection: 'row',
    ,
    DefaultView: 
        flex: 1,
        backgroundColor: '#000',
        width: screenWidth,
        justifyContent:'center',
        alignItems:'center'
    ,
    iconContainer: 
      flexDirection: "row",
      justifyContent: "space-evenly",
      width: 150,
    ,
    backgroundVideo: 
      position: 'absolute',
      top: 0,
      left: 0,
      bottom: 0,
      right: 0,
      width: screenWidth,
      height: 300,
      marginTop:'50%',
      position:'absolute',
  ,
);

我需要一些想法,我们有一个播放器引用要使用,swiper 组件也有 onIndexChanged 它将在我们移动到下一个视频时触发,我们如何链接播放器的引用到onIndexChanged,当我们滑动时,我们如何让它当前视频只播放?

根据 Andrew 的建议,我也使用 InPortView 组件来确定滑动的当前视图,但我仍然不确定如何为要在播放和暂停关注视频的功能中使用的视频元素提供参考。

使用的组件:

对于视频react-native-video

刷卡者:react-native-swiper

使用 Expo 示例更新了完整代码:Expo Snack

【问题讨论】:

查看我对这篇帖子的回答 ***.com/a/54844767/5508175 虽然它使用平面列表,但我认为它可以适应您的情况。 但是你只有一个视频,我有多个视频。 快完成了,对于单个视频它工作正常,但是当我们有多个视频时,它会从该视频停止的地方播放相同的视频 我不确定你的意思。 我的意思是我们如何让它与多个视频一起工作? 【参考方案1】:

所以带上你的零食。我设法让它工作。

我将视频移出到它自己的组件中,并向它传递了一些额外的道具,数组中的index 和显示的currentIndex

export default class App extends React.Component 
  constructor(props) 
    super(props);
    // Your source data
    this.state = 
      images: ,
      muted : false,
      paused: true,
      currentIndex: 0
    ;
  

  onChangeImage = (index) => 
     console.log('currentIndex ', index)
     this.setState( currentIndex: index);
   

  render() 
   let items = Array.apply(null, Array(15)).map((v, i) => 
      return 
        id: i,
        caption: i + 1,
        source:  uri: 'http://placehold.it/200x200?text=' + (i + 1) ,
        dimension: ' width: 150, height: 150 ',
      ;
    );
      return(
        <View style=styles.DefaultView>
          <Swiper
          showsPagination=false
          onIndexChanged=this.onChangeImage
          index=0
          >
           items.map((item, key) => 
             if(key==1 || key ==5)
               return (
                 <VideoPlayer key=key index=key currentIndex=this.state.currentIndex/>
               )
             else
               return(
                 <Image
                   resizeMode='contain'
                   style=width:screenWidth, height: screenHeight
                   source=item.source
                   key=key
               />
              )
             
           )
          </Swiper>
         </View>
      )
  

视频组件使用react-native-inviewport 来帮助处理它是否在视口中。但是它不能很好地与react-native-swiper 配合使用,但可以让它工作。

export default class VideoPlayer extends React.Component 

  pauseVideo = () => 
    if(this.video) 
      this.video.pauseAsync();
    
  

  playVideo = () => 
    if(this.video) 
      this.video.playAsync();
    
  

  handlePlaying = (isVisible) => 
    this.props.index === this.props.currentIndex ?  this.playVideo() : this.pauseVideo();
  

  render() 
      return (
        <View style=styles.container>
          <InViewPort onChange=this.handlePlaying>
            <Video
              ref=ref => this.video = ref
              source= uri: 'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4' 
              rate=1.0
              volume=1.0
              isMuted=false
              resizeMode="cover"
              shouldPlay
              style= width: WIDTH, height: 300 
            />
          </InViewPort>
        </View>
      )
    

当我单独使用InViewPort 组件时,它似乎认为位置 6 的视频在视口中并且会播放它。所以我使用InviewPort 是执行检查以将视频的indexcurrentIndex 进行比较,如果它们匹配则播放视频,否则暂停。我想这可以更新为使用componentDidUpdate 来处理道具的变化。但是,在组件安装时需要执行额外的检查,以便它不会播放视频。

这是我的零食。 https://snack.expo.io/@andypandy/swiper-video

【讨论】:

不用担心。我很高兴它对你有用。这不是一个完美的解决方案,但它似乎可以完成这项工作。我看了一下尝试使用 componentDidMountcomponentDidUpdate 而不是使用 InViewPort 组件,但它仍然在索引 0 上播放视频。我相信可以用它们来做,但它会进一步调查。 得到结果后请及时更新,非常有帮助。作为一个新手,我需要知道我们可以采取什么方法来完成这项工作。请 不确定这是否会随着钩子而改变,但是当应用道具 onIndexChanged 时,我会在堆栈上看到最后一个屏幕,并带有丑陋的闪光灯

以上是关于使用 Swiper 组件播放暂停问题反应原生多视频的主要内容,如果未能解决你的问题,请参考以下文章

如何在本机反应中移动到其他选项卡时暂停视频

在轮播中反应原生视频

在播放视频之前反应原生视频显示缩略图

使用 react-native-video (Android) 在加载和视频播放之间反应原生黑屏一秒钟

HarmonyOS鸿蒙学习笔记(15)Swiper实现抖音切换视频播放效果

HarmonyOS鸿蒙学习笔记(15)Swiper实现抖音切换视频播放效果