flutter实现视频轮播

Posted 阳光照不到的王国

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flutter实现视频轮播相关的知识,希望对你有一定的参考价值。

只要逻辑行得通,代码实现只是迟早的问题。产品经理想要视频轮播的功能,经过分析轮播的逻辑是很简单,只要当一个视频播放完成之后自动播放下一个视频,然后周而复始。前后也花了好几天的时间去尝试,皇天不负有心人,终于有所突破,在此记录一下,给需要的读者参考。

其中需要解决的问题如下:

1、如何获取播放完成的事件

2、在播放完成的事件触发之后如何更改视频源

代码中做注释会解答上面的1、2问题,其实在做的过程中还会遇到其它的棘手问题,尤其是状态改变之后会触发多次build,目前是通过标记位的方式来解决的,现在只是实现了两个视频轮播。

具体代码如下
 

import 'dart:async';
import 'dart:math';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'package:video_player/video_player.dart';

///视频加载组件
class VideoLoader extends StatefulWidget 
  @override
  _VideoLoader createState() 
    return _VideoLoader();
  


class _VideoLoader extends State<VideoLoader> 
  late VideoPlayerController _controller;

  //视频源列表,读者在使用代码时需要将视频源换成你自己的视频源
  List<String> _listVideoUrls = [
    "http://192.168.30.34/ims/resource/17d87da3-4021-48b8-9c68-0d53d0c349df.mp4",
    "http://192.168.30.34/ims/resource/17d87da3-4021-48b8-9c68.mp4"
  ];
  //定义两个标记位用来保证setstate()中的函数只执行一次.
  List<bool> flags = [false, false];


  @override
  void initState() 
    super.initState();
    playVideo1();
     
  
//播放视频源1
  void playVideo1() async 
    _controller = VideoPlayerController.network(_listVideoUrls.elementAt(0));
    print('视频1加载完成');
    _controller.addListener(() async 
      Duration? res = await _controller.position;
      setState(() 
        if (res! >= _controller.value.duration) 


          if (!flags.elementAt(0)) 
            flags[0] = true;
            print('视频1播放完成');
            //移除当前_controller的监听事件
            _controller.removeListener(() );
            _controller.dispose();
            if (flags[1] == true) 
              flags[1] = false;
              print('初始化flags[1] 为false');
            

            playVideo2();
          
        
      );
    );
    _controller.setLooping(false);
    _controller.initialize().then((_) => setState(() ));
    _controller.play();
  

  

  void playVideo2() async 

    _controller = VideoPlayerController.network(_listVideoUrls.elementAt(1));
    print('视频2资源设置完成');
    _controller.addListener(() async 
      Duration? res = await _controller.position;
      setState(() 
        if (res! >= _controller.value.duration) 
          // print('_controller.value.duration:$_controller.value.duration');

          if (!flags.elementAt(1)) 
            flags[1] = true;
            _controller.removeListener(() );
            _controller.dispose();
            print('视频2播放完成');

            if (flags[0] == true) 
              flags[0] = false;
              print('初始化flags[0] 为false');
            
            playVideo1();
          
        
      );
    );
    _controller.setLooping(false);
    _controller.initialize().then((_) => setState(() ));

    _controller.play();
  


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

  @override
  Widget build(BuildContext context) 
    print('build---------------');

    return Scaffold(
      // appBar: CupertinoNavigationBar(
      //   backgroundColor: Colors.white,
      //   middle: const Text('视频播放'),
      // ),

      body: Center(
          child: Container(
        // padding: const EdgeInsets.all(10.0),
        alignment: Alignment.center,

        child: GestureDetector(
          onTap: () ,
          child: Stack(
            alignment: Alignment.bottomCenter,
            children: <Widget>[
              VideoPlayer(_controller),
              //播放倍速
              _ControlsOverlay(controller: _controller),
              //播放进度条
              VideoProgressIndicator(_controller, allowScrubbing: true),
            ],
          ),
        ),
      )),
    );

  


class _ControlsOverlay extends StatelessWidget 
  const _ControlsOverlay(Key? key, required this.controller)
      : super(key: key);

  static const _examplePlaybackRates = [
    0.25,
    0.5,
    1.0,
    1.5,
    2.0,
    3.0,
    5.0,
    10.0,
  ];

  final VideoPlayerController controller;

  @override
  Widget build(BuildContext context) 
    return Stack(
      children: <Widget>[
        AnimatedSwitcher(
          duration: Duration(milliseconds: 50),
          reverseDuration: Duration(milliseconds: 200),
          child: controller.value.isPlaying
              ? SizedBox.shrink()
              : Container(
                  color: Colors.black26,
                  child: Center(
                    child: Icon(
                      Icons.play_arrow,
                      color: Colors.white,
                      size: 100.0,
                    ),
                  ),
                ),
        ),
        GestureDetector(
          onTap: () 
            controller.value.isPlaying ? controller.pause() : controller.play();
          ,
        ),
        Align(
          alignment: Alignment.topRight,
          child: PopupMenuButton<double>(
            initialValue: controller.value.playbackSpeed,
            tooltip: 'Playback speed',
            onSelected: (speed) 
              controller.setPlaybackSpeed(speed);
            ,
            itemBuilder: (context) 
              return [
                for (final speed in _examplePlaybackRates)
                  PopupMenuItem(
                    value: speed,
                    child: Text('$speedx'),
                  )
              ];
            ,
            child: Padding(
              padding: const EdgeInsets.symmetric(
                // Using less vertical padding as the text is also longer
                // horizontally, so it feels like it would need more spacing
                // horizontally (matching the aspect ratio of the video).
                vertical: 12,
                horizontal: 16,
              ),
              child: Text('$controller.value.playbackSpeedx'),
            ),
          ),
        ),
      ],
    );
  


注意,如果项目中没有添加video_player包的话需要先在pubspec.yaml中添加。

 添加方式

在项目中执行 flutter pub add video_player

 添加完成之后 执行 flutter pub get命令。

添加好的pubspec.yaml结构如下:

依赖好之后就可以在项目中使用VideoPlayer相关资源了。

祝君成功,如有疑问可联系笔者交流!

以上是关于flutter实现视频轮播的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 中轮播图详解[Flutter专题31]#yyds干货盘点#

7Flutter banner_view 轮播图的使用

Flutter学习日记之Flutter_swiper实现轮播图功能

flutter 轮播图

安卓基于JCVideoPlayer 播放视频(本地网络),基于java计数器实现视频轮播

Flutter实现马蜂窝小红书自适应高度轮播图