详解Flutter中视频播放器插件的使用教程
作者:迪鲁宾 发布时间:2023-06-15 23:47:31
您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序、电影应用程序和体育相关的应用程序。您是否想知道如何将视频内容添加到您的下一个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插件。
来源:https://juejin.cn/post/7067854786367848478
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- 一 前言在elasticsearch\config目录下,有三个核心的配置文件:elasticsearch.yml,es相关的配置。jvm.
- 什么是ByteBuddyByteBuddy是一个java的运行时代码生成库,他可以帮助你以字节码的方式动态修改java类的代码。为什么需要B
- WinForm RichTextBox文本动态滚动显示文本方在RichTextBox动态显示一些文本信息时,需要一些设置,显示当前要显示的字
- C#byte数组与Image的相互转换实例代码功能需求:1、把一张图片(png bmp jpeg bmp gif)转换为byte数组存放到数
- 本文研究的主要是SpringMVC中使用Thymeleaf模板引擎的相关内容,具体介绍如下。Thymeleaf提供了一组Spring集成,允
- 确保这个修改是正确的(否则将会出现乱码)创建i18n文件夹(就是国际化的意思),然后在此文件加下创login.properties logi
- BigDecimal类对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDe
- 用Flutter实现弹幕功能,轻松实现虎牙、斗鱼的弹幕效果。先来一张效果图:实现原理弹幕的实现原理非常简单,即将一条弹幕从左侧平移到右侧,当
- 前言本文主要给大家介绍了关于Spring4自定义@Value功能的相关内容,使用的Spring版本4.3.10.RELEASE,下面话不多说
- MybatisPlus分页排序查询字段带有下划线如果使用MybatisPlus的自动转驼峰命名法,分页排序查询的字段带有下划线时,会出问题。
- 我们在安装某个APP的时候,基本都会有一个引导页的提示,他们可以打广告,或者介绍新功能的加入和使用说明等。一般都支持滑动并且下面有几个点,显
- 下面是利用Java实现读写文件功能的示例代码读文件TextRead.javaimport java.io.BufferedReader;im
- 比如要获取打开摄像头的应用程序名称,只需要在frameworks/base/core/android/hardware/Camera.jav
- Android的布局管理器本身就是个UI组件,所有的布局管理器都是ViewGroup的子类,而ViewGroup是View的子类,所以布局管
- Socket异常客户端异常java.net.ConnectException: Connection refused: connect。该异
- 一、准备java我已经把java装到了在D盘:二、配置java环境变量点击设置,进入windows设置页面;搜索高级系统设置:在系统变量里添
- Java程序设计 图形用户界面 【二】基本容器JFrameJFrame类的常用操作方法方法作用public JFrame() throws
- 引言使用微信时我们会发现,首次进入微信的好友列表时,会加载好友头像,但是再次进入时,就不用重新加载了,而且其他页面都不用重新加载,说明微信的
- ajax简介 Ajax 即“Asynchronous Javascript An
- 利用栈实现一个简易计算器(Java实现),供大家参考,具体内容如下一、思路分析当我们输入一个类似于“7*2+100-5+