详解Flutter中视频播放器插件的使用教程

目录
  • 创建一个新的视频播放器
  • 添加播放和暂停按钮
  • 创建一个快进
  • 添加一个视频进度指示器
  • 应用视频的字幕
  • 结论

您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序、电影应用程序和体育相关的应用程序。您是否想知道如何将视频内容添加到您的下一个Flutter应用程序中?

从头开始实现视频功能将是一项繁重的任务。但有几个插件可以让开发者的生活变得轻松。视频播放器插件是可用于 Flutter 的最佳插件之一,可满足这一要求。

在这篇文章中,您将学习如何应用视频播放器插件以及控制视频播放器的不同功能。
我们将讨论这些主题。

  • 创建一个新的视频播放器
  • 添加播放和暂停按钮
  • 创建一个快进
  • 添加一个视频进度指示器
  • 应用视频的字幕

创建一个新的视频播放器

在使用视频播放器插件之前,你应该把它添加到你的pubspec.yaml 文件中。当你打开pubspec.yaml 文件时,你可以看到运行你的应用程序所需的一些配置和依赖性。我们的视频播放器插件应该被添加到dependencies 块下。

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  video_player: 2.1.15  //video player

该插件的当前版本是2.1.15 ,但你可以通过查看插件页面在这里添加最新版本。如果你保存文件时是在VS Code中,它会自动下载该插件。如果不是,打开终端,写flutter pub get 来下载该插件。

进入你想添加该插件的文件,并导入video_player.dart 文件。

import 'package:video_player/video_player.dart';

现在你可以在你的项目中使用视频播放器插件了。

有几种方法来加载视频。让我们从资产中加载我们的例子。在项目的根层创建一个assets/video文件夹,在该文件夹内添加一个视频。然后在pubspec.yaml ,在assets 部分,指定文件路径,如下所示。

assets:
    - assets/video/video.mp4

让我们创建一个单独的有状态的部件,称为VideoPlayerWidget ,以插入我们的视频播放器相关的实现。

你可以在initState 方法中初始化视频播放器,如下所示。另外,别忘了dispose ,让视频播放器做清理工作。

class _VideoPlayerState extends State<VideoPlayerWidget> {
  late VideoPlayerController _videoPlayerController;
  @override
  void initState() {
    super.initState();
    _videoPlayerController = VideoPlayerController.asset(
        'assets/video/video.mp4')
      ..initialize().then((_) {
        setState(() {});
        _videoPlayerController.play();
      });
  }

  @override
  void dispose() {
    _videoPlayerController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: VideoPlayer(_videoPlayerController),
    );
  }
}

VideoPlayerController 必须用late 关键字来指定,因为我们在这一行中仍然没有定义视频播放器控制器,我们将在后面做这个。在initState 里面,videoPlayerController 已经和资产的路径一起被初始化。

当初始化完成后,它改变了状态并重建了小部件。你可以在初始化后开始播放视频。

取代assets ,你可以使用视频的URL。为了访问网络,你应该给Android和iOS添加互联网权限配置。

从根目录下,进入ios/Runner ,打开info.plist 文件。然后,在该文件中添加以下配置。

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

接下来,去android/app/src/main ,并打开AndroidManifest.xml 。然后,向其添加以下代码。

<uses-permission android:name="android.permission.INTERNET"/>

现在你可以把asset 改为network ,并在那里添加视频URL。

  @override
  void initState() {
    super.initState();
    _videoPlayerController =
        VideoPlayerController.network('video_url_here')
          ..initialize().then((_) {
            setState(() {});
            _videoPlayerController.play();
          });
  }

即使初始化已经完成,也应该有办法在用户界面中显示播放器。VideoPlayer widget可以用来做到这一点。为了使它工作,你应该把控制器作为第一个参数传递给VideoPlayer widget。

在显示VideoPlayer widget之前,最好先检查初始化是否成功。

  @override
  Widget build(BuildContext context) {
    return Center(
      child: _videoPlayerController.value.isInitialized ? VideoPlayer(_videoPlayerController) : Container(),
    );
  }

现在你可以看到屏幕上的视频了。但是有一个小问题:它的长宽比不合适。这可以通过使用AspectRatio widget来解决。视频播放器提供了一个适当的视频长宽比,你可以使用这个值来设置为AspectRatio widget。

  @override
  Widget build(BuildContext context) {
    return Center(
      child: _videoPlayerController.value.isInitialized ? AspectRatio(aspectRatio:
      _videoPlayerController.value.aspectRatio,
      child: VideoPlayer(_videoPlayerController)
      ) : Container(),
    );
  }

现在你可以看到具有适当长宽比的视频。

添加播放和暂停按钮

首先,让我们把视频播放器小部件包在一个列小部件里面,因为我们应该把播放和暂停按钮放在播放器下面。在播放器小组件之后的列内,让我们在一个Row 小组件内添加两个ElevatedButton 小组件,在这些按钮之间让我们添加一个Padding 小组件以保持一些呼吸空间。

对每个ElevatedButton ,添加相关的Icons ,作为子部件。然后在播放按钮onPressed 的回调里面,你可以参考_videoPlayerController ,并调用play 方法来开始播放视频。在暂停按钮里面,使用pause 方法而不是播放。

现在你可以删除之前在initState 方法里面添加的播放。

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        _videoPlayerController.value.isInitialized ? AspectRatio(aspectRatio:
        _videoPlayerController.value.aspectRatio,
        child: VideoPlayer(_videoPlayerController)
        ) : Container(),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [

            ElevatedButton(onPressed: (){
              _videoPlayerController.pause();
            }, child: Icon(Icons.pause)),
              Padding(padding: EdgeInsets.all(2)),
             ElevatedButton(onPressed: (){
              _videoPlayerController.play();
            }, child: Icon(Icons.play_arrow))
          ],
        )
      ],
    );
  }

另外,你可以给按钮添加样式,得到一个看起来很圆的按钮,这通常是在视频播放器中。

 @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        _videoPlayerController.value.isInitialized
            ? AspectRatio(
                aspectRatio: _videoPlayerController.value.aspectRatio,
                child: VideoPlayer(_videoPlayerController))
            : Container(),
        Padding(
          padding: EdgeInsets.all(20),
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                style: ButtonStyle(
                    backgroundColor: MaterialStateProperty.all<Color>(Colors.blue),
                    fixedSize: MaterialStateProperty.all(Size(70, 70)),
                    shape: MaterialStateProperty.all(RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(100)))),
                onPressed: () {
                  _videoPlayerController.pause();
                },
                child: Icon(Icons.pause)),
            Padding(padding: EdgeInsets.all(2)),
            ElevatedButton(
                style: ButtonStyle(
                    backgroundColor: MaterialStateProperty.all<Color>(Colors.redAccent),
                    fixedSize: MaterialStateProperty.all<Size>(Size(80, 80)),
                    shape: MaterialStateProperty.all(RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(100)))),
                onPressed: () {
                  _videoPlayerController.play();
                },
                child: Icon(Icons.play_arrow))
          ],
        )
      ],
    );
  }

创建一个快进

在实现快进之前,让我们思考一下我们需要什么。首先,应该有一个访问当前视频位置/时间的方法和一个设置新值的方法。控制器的seekTo 方法允许我们为视频设置持续时间。

你可以通过视频播放器value 属性访问当前的视频位置,就像下面这样。

ElevatedButton(
       style: ButtonStyle(
          backgroundColor: MaterialStateProperty.all<Color>(Colors.blue),
          fixedSize: MaterialStateProperty.all(Size(70, 70)),
          shape: MaterialStateProperty.all(RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(100)))),
                onPressed: () {
                  _videoPlayerController.seekTo(Duration(
                   seconds: _videoPlayerController.value.position.inSeconds + 10));
                },
                child: Icon(Icons.fast_forward))

像这样,当用户点击按钮时,你也可以通过减少10 秒来实现向后倒转。

添加一个视频进度指示器

视频播放器插件提供了内置的功能来添加一个进度条以及一些控件。你可以使用VideoProgressIndicator widget来实现这个功能。

作为第一个参数,你必须传递控制器并设置allowScrubbing 属性。allowScrubbing 属性将允许用户通过触摸小组件来滑动进度。通过启用这个,用户可以跳到视频的不同时间戳。此外,你还可以单独控制寻求栏的背景颜色、缓冲区颜色和播放区颜色。

VideoProgressIndicator(
          _videoPlayerController,
          allowScrubbing: true,
          colors: VideoProgressColors(
              backgroundColor: Colors.red,
              bufferedColor: Colors.black,
              playedColor: Colors.blueAccent),
        )

应用视频的字幕

字幕对你的应用程序来说需要两样东西。第一个是不同时期的段落/单词列表,第二个是在视频播放时显示这些标题的方法。为此,应该有一种方法来为时间变化添加一个监听器。

视频播放器包含一个addListener 方法,每秒钟执行一次。你可以使用这个监听器,根据不同的时间段为视频播放器提供字幕。

首先,让我们创建一个Map ,其中包含时间作为一个键,字幕文本作为一个值。在Map ,时间的单位将是秒。

Map<int,String> captions = {
    5:"First subtitle",
    20:"Second subtitle"
  };

接下来,在初始化视频播放器时注册一个Listener 。在回调里面,你可以检查视频是否正在播放,如果视频正在播放,则获得当前的时间为秒。然后,如果当前值包含在captions 地图中,我们可以像下面这样将该值设置为选定的标题。

void initState() {
    super.initState();
    _videoPlayerController =
        VideoPlayerController.asset('assets/video/video.mp4')
        ..addListener(() {
            if(_videoPlayerController.value.isPlaying){
              setState(() {
                if(captions.containsKey(_videoPlayerController.value.position.inSeconds)){
              selectedCaption = captions[_videoPlayerController.value.position.inSeconds];
                }
              });
            }
        })
          ..initialize().then((_) {
            setState(() {});
            _videoPlayerController.play();
          });
  }

现在你可以使用ClosedCaption 来设置那个选定的标题。你可以给标题文本添加一些样式,以获得更好的可见性。

 ClosedCaption(
     text: selectedCaption,textStyle: TextStyle(fontSize: 15,color: Colors.white),)

但是,每次标题改变时,建立主部件并不是好的做法。因此,我们应该把标题逻辑提取到一个单独的小部件。

要注册一个监听器,你应该把视频控制器传递给一个新创建的子部件。

从那里,你可以在子部件内注册监听器。

class VCaption extends StatefulWidget {
  const VCaption(
     this.videoPlayerController,
  );
  final VideoPlayerController videoPlayerController;
  @override
  _VCaptionState createState() => _VCaptionState();
}
class _VCaptionState extends State<VCaption> {
  String? selectedCaption = "";
  Map<int,String> captions = {
    5:"First subtitle",
    20:"Second subtitle"
  };

  @override
  void initState() {
    widget.videoPlayerController.addListener(() {
      if(widget.videoPlayerController.value.isPlaying){
              print("Time ${widget.videoPlayerController.value.position.inSeconds}");
              setState(() {
                if(captions.containsKey(widget.videoPlayerController.value.position.inSeconds)){
              selectedCaption = captions[widget.videoPlayerController.value.position.inSeconds];
                }
              });
            }
    });
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return ClosedCaption(
      text: selectedCaption,textStyle: TextStyle(fontSize: 15,color: Colors.white),);
  }
}

现在我们可以在之前创建的栏目内添加这个小部件,并将_videoPlayerController 作为参数传递。你可以在把小部件添加到树上之前检查视频播放器是否已经被初始化,就像下面这样。

 _videoPlayerController.value.isInitialized ? VCaption(_videoPlayerController) : Container(),

你可以使用Stack widget在视频顶部显示这些字幕,而不是在视频下面显示那些字幕。字幕以及进度指示器已经被移到了Stack widget里面,以便在视频的顶部显示。

 Stack(
          children: [
            _videoPlayerController.value.isInitialized
                ? AspectRatio(
                    aspectRatio: _videoPlayerController.value.aspectRatio,
                    child: VideoPlayer(_videoPlayerController))
                : Container(),
            Positioned(
              bottom: 2,
              width: MediaQuery.of(context).size.width,
              child: _videoPlayerController.value.isInitialized
                  ? VCaption(_videoPlayerController)
                  : Container(),
            ),
            Positioned(
                bottom: 0,
                width: MediaQuery.of(context).size.width,
                child: VideoProgressIndicator(
                  _videoPlayerController,
                  allowScrubbing: false,
                  colors: VideoProgressColors(
                      backgroundColor: Colors.blueGrey,
                      bufferedColor: Colors.blueGrey,
                      playedColor: Colors.blueAccent),
                ))
          ],
        )

结论

使用视频播放器插件而不是从头开始实现一个视频播放器,可以节省大量的开发时间,并提供所有开箱即用的功能。

如果您想超越这些定制,实现一个具有Material-和Cupertino灵感的漂亮的视频播放器,您可以选择chewie Flutter插件

以上就是详解Flutter中视频播放器插件的使用教程的详细内容,更多关于Flutter视频播放器插件的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android实现视频的画中画功能

    简介: Android 8.0(API 级别 26)允许以画中画 (PIP) 模式启动 Activity.画中画是一种特殊类型的多窗口模式,最常用于视频播放.使用该模式,用户可以通过固定到屏幕一角的小窗口观看视频,同时在应用之间进行导航或浏览主屏幕上的内容. 画中画窗口会显示在屏幕的最上层,位于系统选择的一角.您可以将画中画窗口拖动到其他位置(会自动贴边).当您点按该窗口时,会看到两个特殊的控件:全屏切换开关(位于窗口的中心)和关闭按钮(右上角的"X"). 效果图: 1.声明对画中画的

  • Android实现音乐视频播放

    本文实例为大家分享了Android实现音乐视频播放的具体代码,供大家参考,具体内容如下 步骤 1.新建一个安卓项目,再加一个assets包 2.在 assets中加入一段音频 3.在界面中加入音乐的"开始"按钮和"暂停"按钮. 4.在 MainActivity文件中写相应逻辑 package com.hnucm.c201901020110; import androidx.annotation.RequiresApi; import androidx.appcomp

  • Android实现微信朋友圈图片和视频播放

    本文实例为大家分享了Android实现微信朋友圈图片和视频播放的具体代码,供大家参考,具体内容如下 1.效果图: 2.源码地址:链接 3.参数控制,是否显示播放按钮 holder.layout.setIsShowAll(mList.get(position).isShowAll); holder.layout.setIsVideo(true); //true :video, false :img holder.layout.setUrlList(mList.get(position).urlLi

  • Android使用vitamio插件实现视频播放器

    使用第三方的vitamio插件实现简易的播放器.vitamio版本(5.2.3) 官网地址:官网地址 效果展示 效果 项目结构 代码: MainActivity package com.example.www.app; import android.app.ListActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Li

  • Flutter实现用视频背景的登录页的示例代码

    最终效果 项目地址 https://github.com/Tecode/flutter_widget 实现方法 安装插件 安装video_player,我安装的是最新的版本,请根据你自己的flutter版本去安装对应的版本,安卓可以直接使用虚拟机,IOS需要真机才可以播放. dev_dependencies: flutter_test: sdk: flutter video_player: ^0.10.1+6 我的Flutter版本 Flutter 1.7.8+hotfix.4 • channe

  • 详解Flutter中视频播放器插件的使用教程

    目录 创建一个新的视频播放器 添加播放和暂停按钮 创建一个快进 添加一个视频进度指示器 应用视频的字幕 结论 您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序.电影应用程序和体育相关的应用程序.您是否想知道如何将视频内容添加到您的下一个Flutter应用程序中? 从头开始实现视频功能将是一项繁重的任务.但有几个插件可以让开发者的生活变得轻松.视频播放器插件是可用于 Flutter 的最佳插件之一,可满足这一要求. 在这篇文章中,您将学习如何应用视频播放器插件以及控制视频播放器

  • 详解Flutter中网络框架dio的二次封装

    其实dio框架已经封装的很好了,但是在实战项目中,为了项目可以统一管理,还是需要对dio框架进行二次封装. 整体思路:一般情况下,后台返回的数据我们可以分为两部分 1.状态数据 2.渲染数据 状态数据就是接口有没有正常返回数据相关的数据,这部分数据跟业务无关,我们可以封装起来统一管理,渲染数据就是我们渲染页面所需要的数据,这块的数据需要我们自己处理. 接下来我们就主要处理渲染数据这块的内容,我定义了两个函数,渲染数据可能为一个对象或者一个数组,我做了分别处理,定义两个函数来接受渲染数据. //

  • 详解Flutter中数据传递的方式

    目录 1.构造方法传递 2.InheritedWidget 3.Notification 4.Stream & event_bus 在Flutter中,常见的数据传递一共有以下几种: 1.构造方法传递 Flutter的构造方法具备着dart语言的特点,参数具备可选状态,通过构造方法传递数据,可以很方便的将任意数据进行传递,平时开发中,A跳转B页面最常用的方法就是通过构造方法进行传递.比如我们最常见的Key就是通过构造一级一级向下传递的. 优点: 相邻页面之间传递数据非常方便,你不需要进行任何额外

  • 详解Flutter中StatefulBuilder组件的使用

    目录 例子 预览 编码 结论 本文是关于 Flutter 中的 StatefulBuilder 小部件.我将介绍小部件的基础知识,然后检查一个在实际中使用它的完整示例..StatefulBuilder 小部件可以在这些区域的状态发生变化时仅重建某些小区域而无需付出太多努力.这提高了应用程序的性能. StatefulBuilder({ Key? key, required StatefulWidgetBuilder builder r}) builder 函数有两个参数:context和一个用于在

  • 详解IDEA中类加载器调用getResourceAsStream()方法需注意的问题

    当我们使用类加载器调用getResourceAsStream()时,经常会出现空指针异常,明明路径名称都没有问题,为什么就是报空指针异常呢? 查了一下getResourceAsStream()的用法: 1. Class.getResourceAsStream(String path) : path 不以'/'开头时默认是从此类所在的包下取资源,以'/'开头则是从ClassPath根下获取.其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源. 2. Class.getCl

  • 详解Flutter中的数据传递

    目录 Flutter 中的数据传递 InheritedWidget EventBus 总结 Flutter 中的数据传递 在开发中,数据从一个页面传递到另一个页面事很常用的,在Android 开发中,通常是通过把数据放到 intent 中传递过去.在 Flutter 中,数据是如何传递的呢? 在Flutter 中一切都是Widget,所以数据的传递就成了数据才Widget 中的传递.在之前的学习中,数据从一个Widget 传递到 子 Widget 是通过构造函数,一层一层的往里面传,要是 wid

  • 详解Flutter中Dart集合使用教程

    目录 前言 优先使用集合的特有语法 不要使用.length 属性判断集合是不是为空 避免使用 forEach 迭代元素 不要使用 List.from(),除非你想要更改结果的类型 使用 whereType 过滤类型 避免使用 cast() 做强制转换 总结 前言 集合是应用程序中最为常见的数据结构,Dart 一共支持如下四种集合,其中核心的 List, Map 和 Set 在基础框架中,而 Queue 在 dart:collection 库定义. 列表:也就是 List类,可动态增长的数组: k

  • 详解SpringMVC中拦截器的概念及入门案例

    目录 一.拦截器概念 二.拦截器入门案例 一.拦截器概念 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行 作用: 在指定的方法调用前后执行预先设定的代码 阻止原始方法的执行 拦截器与过滤器区别  归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术 拦截内容不同:Filter对所有的访问进行增强,Interceptor仅针对SpringMVC的访问进行增强 二.拦截器入门案例 1.声明拦截器的

  • 详解flutter中常用的container layout实例

    目录 简介 Container的使用 旋转Container Container中的BoxConstraints 总结 简介 在上一篇文章中,我们列举了flutter中的所有layout类,并且详细介绍了两个非常常用的layout:Row和Column. 掌握了上面两个基本的layout还是不够的,如果需要应付日常的layout使用,我们还需要掌握多一些layout组件.今天我们会介绍一个功能强大的layout:Container layout. Container的使用 Container是一

  • 详解Java中的mapstruct插件使用

    实体类的属性映射怎么可以少了它? 我们都知道,随着一个工程的越来越成熟,模块划分会越来越细,其中实体类一般存于 domain 之中,但 domain 工程最好不要被其他工程依赖,所以其他工程想获取实体类数据时就需要在各自工程写 model,自定义 model 可以根据自身业务需要映射相应的实体属性.这样一来,这个映射工程貌似并不简单了.阿森差点就犯难了…… 序 所以阿淼今天就要给大家安利一款叫 mapstruct 的插件,它就是专门用来处理 domin 实体类与 model 类的属性映射的,我们

随机推荐