咱们每每写项目都是着急上手,总想着先写后面有时间了再(说)来(的)优(好)化(听),这样写出来的代码每每都是跟业务系统耦合在一块要么就是质量不高,下次使用的时候就想重构,有人说项目急没办法(曾经我也这么说过),可是一个好的编程习惯真的能够作到事半功倍。既然是一种习惯,那么确定是能够改的,首先我要先习惯利用思惟导图来明确明白本身要什么,有什么功能,开始设计接口以及参数,最后才是分优先级而后根据优先级来执行下一步该作什么,这样能够很大高效的避免踩坑,避免由于设计不合理须要重构就麻烦了。闲话很少说下面进入正题。git
那么什么叫高度自由的播放器呢?我是这么认为的:首先尽量的开放权限来更改配置,其次模块化设计,同时还须要跟业务代码解耦,光有这些还不算够,最后咱们须要让视频播放器实现自定义拓展,也就是说现有播放器功能知足不了本身需求的时候,开发者能够本身动手,例如视频的字幕
,弹幕
,视频顶部控制栏
等。github
经过上图咱们能够看一下播放器都有哪些属性呢?编程
播放器属性:数组
属性 | 类型 | 描述 |
---|---|---|
dataSource | String | 视频URL或媒体文件的路径 |
children | List | 自定义拓展的子元素,须要使用 WidgetAlign (字幕、弹幕、视频顶部控制栏等) |
onplay | VideoCallback | 视频开始播放的回调 |
onpause | VideoCallback | 视频暂停播放回调 |
ontimeupdate | VideoCallback | 视频播放进度回调(经过返回的value进行字幕匹配) |
onend | VideoCallback | 视频播放结束回调 |
playOptions | VideoPlayOptions | 视频播放自定义配置(详情见下方的Useage) |
videoStyle | VideoStyle | 视频播放器自定义样式(详情见下方的Useage) |
播放器自定义配置 (VideoPlayOptions):缓存
属性 | 类型 | 描述 |
---|---|---|
startPosition | Duration | 开始播放节点,例如:Duration(seconds: 0)) |
loop | bool | 是否循环播放 |
seekSeconds | num | 设置视频快进/快退单位秒数 |
autoplay | bool | 是否自动播放 |
aspectRatio | num | 视频播放比例,例如:16/9 或者 4/3 |
allowScrubbing | bool | 是否运行进度条拖拽 |
播放器自定义样式 (VideoStyle):bash
属性 | 类型 | 描述 |
---|---|---|
playIcon | Widget | 视频暂停播放时中央显示的图标,showPlayIcon为false 时,该属性设置无效。 |
showPlayIcon | bool | 暂停时是否显示播放按钮 |
videoControlBarStyle | VideoControlBarStyle | 控制栏自定义样式 |
videoSubtitlesStyle | VideoSubtitles | 字幕自定义样式 |
控制栏自定义样式 (VideoControlBarStyle):微信
属性 | 类型 | 描述 |
---|---|---|
barBackgroundColor | Color | 控制栏背景颜色,默认为Color.fromRGBO(0, 0, 0, 0.5) |
playedColor | Color | 已播放的进度条颜色(下图1 详细说明) |
bufferedColor | Color | 已缓冲的进度条颜色(下图1 详细说明) |
backgroundColor | Color | 进度条背景颜色(下图1 详细说明) |
playIcon | Widget | 控制栏播放图标(下图2 详细说明) |
pauseIcon | Widget | 控制栏暂停图标(下图2 详细说明) |
rewindIcon | Widget | 控制栏快退图标(下图2 详细说明) |
forwardIcon | Widget | 控制栏快进图标(下图2 详细说明) |
fullscreenIcon | Widget | 控制栏全屏图标(下图2 详细说明) |
fullscreenExitIcon | Widget | 控制栏取消全屏图标(下图2 详细说明) |
itemList | List | 控制栏自定义功能(下图3 详细说明),默认为["rewind", "play", "forward", "progress", "time", "fullscreen"]。若是咱们须要调整控制栏显示的顺序,仅须要调整 list 中字符串的顺序,若是须要删减,直接从 list 中移除改字符串便可,例如移除快进和快退,则讲 list 设置为 ["play", "progress", "time", "fullscreen"] 便可。后面会陆续开放自定义元素,也就是你把你的元素加入到 list 中。 |
添加依赖,打开根目录的pubspec.yaml
文件,在dependencies:
下面添加如下代码app
awsome_video_player: #latest
复制代码
安装依赖(若是已经自动安装请忽略)ide
cd 项目目录
flutter packages get
复制代码
在页面中引入库模块化
import 'package:awsome_video_player/awsome_video_player.dart';
复制代码
这是一个完整的
main.dart
import 'package:flutter/material.dart';
import 'package:awsome_video_player/awsome_video_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String mainSubtitles = "主字幕";
String subSubtitles = "辅字幕";
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Awsome video player'),
),
body: Center(
child: AwsomeVideoPlayer(
"https://www.runoob.com/try/demo_source/movie.mp4",
/// 视频播放配置
playOptions: VideoPlayOptions(
seekSeconds: 30,
aspectRatio: 16 / 9,
loop: true,
autoplay: true,
allowScrubbing: true,
startPosition: Duration(seconds: 0)),
/// 自定义视频样式
videoStyle: VideoStyle(
/// 自定义视频暂停时视频中部的播放按钮
playIcon: Icon(
Icons.play_circle_outline,
size: 100,
color: Colors.white,
),
/// 暂停时是否显示视频中部播放按钮
showPlayIcon: true,
/// 自定义底部控制栏
videoControlBarStyle: VideoControlBarStyle(
/// 自定义颜色
//playedColor: Colors.red,
//bufferedColor: Colors.yellow,
//backgroundColor: Colors.green,
//barBackgroundColor: Colors.blue,
/// 更改进度栏的播放按钮
playIcon: Icon(
Icons.play_arrow,
color: Colors.white,
size: 16
),
/// 更改进度栏的暂停按钮
pauseIcon: Icon(
Icons.pause,
color: Colors.red,
size: 16,
),
/// 更改进度栏的快退按钮
rewindIcon: Icon(
Icons.replay_30,
size: 16,
color: Colors.white,
),
/// 更改进度栏的快进按钮
forwardIcon: Icon(
Icons.forward_30,
size: 16,
color: Colors.white,
),
/// 更改进度栏的全屏按钮
fullscreenIcon: Icon(
Icons.fullscreen,
size: 16,
color: Colors.white,
),
/// 更改进度栏的退出全屏按钮
fullscreenExitIcon: Icon(
Icons.fullscreen_exit,
size: 16,
color: Colors.red,
),
/// 决定控制栏的元素以及排序,示例见上方图3
itemList: [
"rewind",
"play",
"forward",
"progress",
"time",
"fullscreen"
],
),
/// 自定义字幕
videoSubtitlesStyle: VideoSubtitles(
mianTitle: Align(
alignment: Alignment.bottomCenter,
child: Container(
padding: EdgeInsets.fromLTRB(10, 0, 10, 30),
child: Text(
mainSubtitles,
maxLines: 2,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white, fontSize: 14)),
),
),
subTitle: Align(
alignment: Alignment.bottomCenter,
child: Container(
padding: EdgeInsets.all(10),
child: Text(
subSubtitles,
maxLines: 2,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white, fontSize: 14)),
),
),
),
),
/// 自定义拓展元素
children: [
/// 添加自定义视频顶部返回按钮
Align(
alignment: Alignment.topLeft,
child: GestureDetector(
onTap: () {
print("This is test from children.");
},
child: Container(
margin: EdgeInsets.only(top: 5, left: 5),
width: 30,
height: 30,
decoration: BoxDecoration(
color: Color.fromRGBO(0, 0, 0, .5),
borderRadius: BorderRadius.all(Radius.circular(15)),
),
child: Icon(Icons.arrow_back, size: 16, color: Colors.white,)
),
),
),
/// 这个将会覆盖的视频内容,由于这个层级是最高级,所以手势会失效(慎用)
/// 这个能够用来作视频广告
// Positioned(
// top: 0,
// left: 0,
// bottom: 0,
// right: 0,
// child: Text("data", style: TextStyle(color: Colors.white),),
// ),
],
/// 视频暂停回调
onpause: (value) {
print("video paused");
},
/// 视频播放回调
onplay: (value) {
print("video played");
},
/// 视频播放结束回调
onended: (value) {
print("video ended");
},
/// 视频播放进度回调
/// 能够用来匹配字幕
ontimeupdate: (value) {
print("timeupdate ${value}");
var position = value.position.inMilliseconds / 1000;
//根据 position 来判断当前显示的字幕
},
),
),
),
);
}
}
复制代码
首先我来看一下控制栏的图标自定义(见上图2):
DEMO: main.dart
import 'package:flutter/material.dart';
import 'package:awsome_video_player/awsome_video_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Awsome video player'),
),
body: Center(
child: AwsomeVideoPlayer(
"https://www.runoob.com/try/demo_source/movie.mp4",
/// 视频播放配置
playOptions: VideoPlayOptions(
seekSeconds: 30,
aspectRatio: 16 / 9,
loop: true,
autoplay: true,
allowScrubbing: true,
startPosition: Duration(seconds: 0)),
/// 自定义视频样式 - 请注意我要划重点了
videoStyle: VideoStyle(
/// 自定义底部控制栏 - 这是重点了
videoControlBarStyle: VideoControlBarStyle(
/// 更改进度栏的播放按钮
playIcon: Icon(
Icons.play_arrow,
color: Colors.white,
size: 16
),
/// 更改进度栏的暂停按钮
pauseIcon: Icon(
Icons.pause,
color: Colors.red,
size: 16,
),
/// 更改进度栏的快退按钮
rewindIcon: Icon(
Icons.replay_30,
size: 16,
color: Colors.white,
),
/// 更改进度栏的快进按钮
forwardIcon: Icon(
Icons.forward_30,
size: 16,
color: Colors.white,
),
/// 更改进度栏的全屏按钮
fullscreenIcon: Icon(
Icons.fullscreen,
size: 16,
color: Colors.white,
),
/// 更改进度栏的退出全屏按钮
fullscreenExitIcon: Icon(
Icons.fullscreen_exit,
size: 16,
color: Colors.red,
),
),
),
),
),
),
);
}
}
复制代码
咱们能够根据videoStyle
中videoControlBarStyle
来自定义控制栏的样式:调整顺序(见上方图3)只须要调整 itemList
中字符串的顺序便可;控制显示的元素,将不须要暂时的元素从 itemList
中删除便可。
DEMO: main.dart
import 'package:flutter/material.dart';
import 'package:awsome_video_player/awsome_video_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Awsome video player'),
),
body: Center(
child: AwsomeVideoPlayer(
"https://www.runoob.com/try/demo_source/movie.mp4",
/// 视频播放配置
playOptions: VideoPlayOptions(
seekSeconds: 30,
aspectRatio: 16 / 9,
loop: true,
autoplay: true,
allowScrubbing: true,
startPosition: Duration(seconds: 0)),
/// 自定义视频样式 - 请注意我要划重点了
videoStyle: VideoStyle(
/// 自定义底部控制栏 - 这是重点了
videoControlBarStyle: VideoControlBarStyle(
/// 决定控制栏的元素以及排序,示例见上方图3
itemList: [
"progress",// 这里将进度条前置了,所以有了图3的效果
"rewind",//若是须要删除快退按钮,将其注释或删除便可
"play",
"forward",
"time",
"fullscreen"
],
),
),
),
),
),
);
}
}
复制代码
一样咱们仍是经过videoStyle
中videoControlBarStyle
来自定义进度条的颜色(见上方图3)。
DEMO: main.dart
import 'package:flutter/material.dart';
import 'package:awsome_video_player/awsome_video_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Awsome video player'),
),
body: Center(
child: AwsomeVideoPlayer(
"https://www.runoob.com/try/demo_source/movie.mp4",
/// 视频播放配置
playOptions: VideoPlayOptions(
seekSeconds: 30,
aspectRatio: 16 / 9,
loop: true,
autoplay: true,
allowScrubbing: true,
startPosition: Duration(seconds: 0)),
/// 自定义视频样式
videoStyle: VideoStyle(
/// 自定义底部控制栏
videoControlBarStyle: VideoControlBarStyle(
/// 自定义颜色
playedColor: Colors.red,//已播放进度条的颜色
bufferedColor: Colors.yellow,//已缓存进度条的颜色
backgroundColor: Colors.green,//进度条的背景颜色
barBackgroundColor: Colors.blue,//控制栏的背景颜色
),
),
),
),
),
);
}
}
复制代码
视频若是须要横竖屏不能使用safeArea
视频的 dataSoure
不能为空,为空时使用加载视图,不然播放器会报错
import 'package:flutter/material.dart';
import 'package:awsome_video_player/awsome_video_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String videoUrl = "https://www.runoob.com/try/demo_source/movie.mp4";
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Awsome video player'),
),
body: Center(
/// 通常videoUrl是从服务端返回,在没有返回来以前,
/// 咱们可使用加载视图来占位
child: videoUrl != "" ? AwsomeVideoPlayer(
videoUrl,
/// 视频播放配置
playOptions: VideoPlayOptions(
seekSeconds: 30,
aspectRatio: 16 / 9,
loop: true,
autoplay: true,
allowScrubbing: true,
startPosition: Duration(seconds: 0)),
) : AspectRatio(
aspectRatio: 16 / 9,
child: Center(
child: CircularProgressIndicator(strokeWidth: 2.0),
),
),
),
),
);
}
}
复制代码
AwsomeVideoPlayer
下面的children
仅支持Align
和Positioned
,children的层级会高于下面,这个功能会持续更新,后面会陆续出一些针对自定义拓展的高阶文档。
开发过程当中遇到问题,请经过如下方式联系我,我会第一时间回复你:
Copyright © 2020, Mark Chen. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.