Flutter Video Player On Click 传递 URL 动态并加载要播放的视频

Posted

技术标签:

【中文标题】Flutter Video Player On Click 传递 URL 动态并加载要播放的视频【英文标题】:Flutter Video Player On Click Pass URL dynamic and Load Video to play 【发布时间】:2020-05-12 15:53:04 【问题描述】:

sample screen of video player attached below 我怎样才能让视频播放器动态播放,同时通过传递视频URL点击列表播放视频?

点击时我通过了 URL 并尝试重新初始化并开始播放它不工作,状态没有改变

这是我的代码,

videoplayerscreen.dart,

class VideoPlayerScreen extends StatefulWidget 
  int playBackTime;
  int playBackTotalTime;
  String setPlayTime;
  String setPlayDuration;
  double aspectRatio;
  String videoUrl;
  bool isForward;
  bool isFullScreen;
  bool allowFullScreen;
  bool showControls;
  bool isAutoPlay;
  int startWithinSeconds;

  VideoPlayerScreen(
    Key key,
    this.playBackTime = 0,
    this.playBackTotalTime = 0,
    this.setPlayTime = "00:00",
    this.setPlayDuration = "00:00",
    this.aspectRatio = 16 / 9,
    this.videoUrl =
        "",
    this.isForward = true,
    this.isFullScreen = false,
    this.allowFullScreen = false,
    this.showControls = true,
    this.isAutoPlay = false,
    this.startWithinSeconds = 0,
  ) : super(key: key);

  @override
  _VideoPlayerScreenState createState() => _VideoPlayerScreenState();


class _VideoPlayerScreenState extends State<VideoPlayerScreen> 
  VideoPlayerController _controller;

  void initPlayer() async 
    _controller = VideoPlayerController.network(widget.videoUrl);
    await _controller.initialize();
    _controller.setLooping(true);
    _controller.seekTo(Duration(seconds: widget.startWithinSeconds));
    if (widget.isAutoPlay) 
      _controller.play();
    
    _controller.addListener(() 
      setState(() 
        widget.playBackTime = _controller.value.position.inSeconds;
        widget.setPlayTime = timeFormatter(widget.playBackTime);
      );
    );
  

  @override
  void initState() 
    initPlayer();
    super.initState();
  

 @override
  void dispose() 
    _controller.dispose();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
    super.dispose();
  

在配置中,

video_player: ^0.10.5

调用其他类 CourseDetails.dart ,

             Container(
                  padding: EdgeInsets.only(left: 20.0, right: 20.0),
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(8.0),
                    child: _playUrl != null
                        ? VideoPlayerScreen(videoUrl: _playUrl)
                        : Image.asset(
                            'assets/images/test_video_player_screen.png'),
                  ),
                )
GestureDetector(
 **here i am changing the state **
      onTap: () 
        setState(() 
            _playUrl = videoLists['course_video_url'];
        );
      ,
      child: Padding(
        padding:
            EdgeInsets.only(left: 10.0, right: 20.0, top: 2.0, bottom: 5.0),
        child: Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Text(
              "$videoLists['sn_no']",
              textAlign: TextAlign.center,
              style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                  color: Colors.black45,
                  fontFamily: 'Oswald-SemiBold'),
            ),
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: EdgeInsets.only(left: 10.0),
                  child: Text(
                    "$videoLists['course_video_title']",
                    textAlign: TextAlign.left,
                    style: TextStyle(
                        fontSize: 14,
                        fontWeight: FontWeight.bold,
                        color: Colors.black45,
                        fontFamily: 'Oswald-SemiBold'),
                  ),
                ),
                Row(
                  children: <Widget>[
                    Padding(
                      padding: EdgeInsets.only(left: 10.0),
                      child: Text(
                        "Video - $videoLists['course_video_duration']",
                        textAlign: TextAlign.left,
                        style: TextStyle(
                            fontSize: 12,
                            fontWeight: FontWeight.bold,
                            color: Colors.grey,
                            fontFamily: 'Oswald-SemiBold'),
                      ),
                    ),
                    Padding(
                        padding: EdgeInsets.only(left: 5.0),
                        child: videoLists['course_watched']
                            ? Image.asset(
                                'assets/images/green_tick_icon.png',
                                width: 12.0,
                                height: 12.0,
                              )
                            : null),
                  ],
                ),
              ],
            ),
          ],
        ),
      ),
    )

【问题讨论】:

您能解释一下您在setState 上的onTap 上的这个类初始化做什么吗?这段代码中很少有令人困惑的地方,使我们难以帮助您调试。 你当然会解释,实际上我已经创建了两个类, 1.VideoPlayerScreen 2.CourseDetails 在 CourseDetails.dart 中,我正在调用其余的 api 来获取 VideoURL 的列表并显示在列表视图中, onTap 在用户单击特定列表项时被调用。那时我将 URL 传递给 VideoPlayerScreen.dart 来播放视频,因此在第一次播放时,在下一次点击时,视频 url 正在传递但视频没有播放,帮我解决它如何在传递 URL @JoãoSoares 时动态播放视频播放器 【参考方案1】:

感谢所有回复。我得到了解决方案:

Build 函数中,我检查了是否发生了任何 url 更改。如果发生变化,我处理旧控制器并重新初始化视频控制器。然后,它对我来说很好。

@override
Widget build(BuildContext context) 
    if (currentObjectVideoUrl != widget.videoUrl) 
       _controller.dispose();
       initPlayer();
    

【讨论】:

如何找到 currentObjectVideoUrl ?【参考方案2】:

您可以通过创建一个传递 URL 的有状态小部件来实现此目的。然后在init方法里面,就可以这样做了

class ViewVideo extends StatefulWidget 
  final link;
  ViewVideo(this.link);
  @override
  _ViewVideoState createState() => _ViewVideoState(this.link);


class _ViewVideoState extends State<ViewVideo> 
  final link;
  _ViewVideoState(this.link);

  @override
  void initState() 
    super.initState();
    //Write your video player code here
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Container(),
    );
  

  @override
  void dispose() 
     //Here you can close the video player
     super.dispose();
  

【讨论】:

我尝试过同样的事情但仍然无法正常工作,它不会破坏旧视频,也不会播放新视频@K K 我已经修改了问题并简单地添加了我的代码@K K 您必须添加 dispose 方法并关闭现有控制器。检查我更新的代码。 是的,我已经添加了`@override void dispose() _controller.dispose(); SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeRight, DeviceOrientation.landscapeLeft, DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); super.dispose(); ` @KK,我也试过你的方法。它不工作。【参考方案3】:

我已根据您的 cmets 修改了我的回复。您只需要将视频网址放在您使用 setState 更改的类变量上。然后在您的小部件上检查变量是否存在并决定显示VideoPlayerScreen 小部件或空框。

String videoUrl = '';

@override
Widget build(BuildContext context) 
  return Column(
    children: <Widget>[
      videoUrl == '' ? SizedBox() : VideoPlayerScreen(videoUrl: videoUrl),
      RaisedButton(
        onPressed: () 
          setState(()
            videoUrl == videoLists['course_video_url'];
          );
        
      ),
    ],
  );

【讨论】:

嗨,但我在一个屏幕上做,这里我附上设计的图像,(i.stack.imgur.com/PoeyX.png)在这个 URL 的图像列表中点击我在顶部播放视频@若昂·苏亚雷斯 @Jai 我已经修改了我的回复以符合您的评论。 @Jai 你的 VideoPlayerScreen 类中显示视频的 build 方法在哪里,你能分享一下吗? VideoPlayerScreen 构建方法,` @override Widget build(BuildContext context) if (_controller.value.initialized) AspectRatio( aspectRatio: widget.aspectRatio, child: VideoPlayer(_controller), ) ` @Joao Soares【参考方案4】:

你可以使用didUpdateWidget方法。

我们可以比较 Widget 类的任何属性,并据此重置播放器。

对于重置,一般步骤是

    停止播放器 关闭会话 再次初始化播放器(使用新的 URL 和其他参数)

下面是逻辑的代码sn-p。

class _VideoPlayerScreenState extends State<VideoPlayerScreen> 
  VideoPlayerController _controller;

  void initPlayer() async 
    /// initialise player
  

  void disposePlayer() 
    /// dispose player
  

  void resetPlayer() 
    disposePlayer();
    initPlayer();
  

  @override
  void initState() 
    initPlayer();
    super.initState();
  

  @override
  void didUpdateWidget(VideoPlayerScreen oldWidget) 
    super.didUpdateWidget(oldWidget);

    if (oldWidget.videoUrl != widget.videoUrl) 
      resetPlayer();
    
  

  @override
  void dispose() 
    disposePlayer();
    super.dispose();
  

didUpdateWidget 方法的参考。

【讨论】:

以上是关于Flutter Video Player On Click 传递 URL 动态并加载要播放的视频的主要内容,如果未能解决你的问题,请参考以下文章

flutter视频播放videoplayer与chewie

Flutter开发--视频播放器

如何在 video_player 上无延迟地连续播放视频?

Qt/C++ Multimedia Player Video Clips,多个视频小部件

Vue中使用vue-video-player插件播放视频时src动态配置-指定范围整数随机获取拼接url

视频播放平台vue-core-video-player