flutter video_player电影播放,进度条,快进,手势亮度音量,全屏
flutter 播放 进度条 电影 全屏 手势 Video 亮度
2023-09-14 09:04:28 时间
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:screen_brightness/screen_brightness.dart';
import 'package:social_im/pages/group/MovieLandScapeLeft.dart';
import 'package:video_player/video_player.dart';
import '../../common/Global.dart';
import '../../router.dart';
import '../../utils/date_util.dart';
class MovieRoom extends StatefulWidget {
String fileUrl = '';
MovieRoom(this.fileUrl) {}
@override
State<StatefulWidget> createState() => MovieRoomState();
}
class MovieRoomState extends State<MovieRoom> {
VideoPlayerController? _controller;
//获取当前视频播放的信息
late VideoPlayerValue videoPlayerValue;
//当前播放视频的总时长
late Duration totalDuration;
//当前播放视频的位置
late Duration currentDuration;
//当前视频是否缓存
bool isBuffer = false;
bool isPlay = false;
bool isPress = false;
late Timer? isPressTimer;
String tDuration = "0:00:00";
String cDuration = "0:00:00";
late Offset startPosition; // 起始位置
late double movePan; // 偏移量累计总和
late double layoutWidth; // 组件宽度
late double layoutHeight; // 组件高度
String volumePercentage = ''; // 组件位移描述
bool allowHorizontal = false; // 是否允许快进
Duration position = const Duration(seconds: 0); // 当前时间
double brightness = 0.0; //亮度
bool brightnessOk = false; // 是否允许调节亮度
bool showSettingDialog = true;
@override
void initState() {
isPressTimer = Timer(const Duration(), () {});
if (widget.fileUrl.startsWith("http://") ||
widget.fileUrl.startsWith("https://")) {
_controller = VideoPlayerController.network(widget.fileUrl)
..initialize().then((_) {
EasyLoading.dismiss();
_controller!.play();
mySetState(() {});
});
} else if (widget.fileUrl.startsWith('assets/')) {
_controller = VideoPlayerController.asset(widget.fileUrl)
..initialize().then((_) {
EasyLoading.dismiss();
_controller!.play();
mySetState(() {});
});
} else {
_controller = VideoPlayerController.file(File(widget.fileUrl))
..initialize().then((_) {
EasyLoading.dismiss();
_controller!.play();
mySetState(() {});
});
}
if (_controller != null) {
_controller!.removeListener(() {});
_controller!.addListener(() {
mySetState(() {
isPlay = _controller!.value.isPlaying;
videoPlayerValue = _controller!.value;
totalDuration = videoPlayerValue.duration;
currentDuration = videoPlayerValue.position;
tDuration = totalDuration.toString().substring(0, 7);
cDuration = currentDuration.toString().substring(0, 7);
isBuffer = videoPlayerValue.isBuffering;
});
});
}
super.initState();
}
mySetState(callBack) {
if (mounted) {
setState(() {
callBack();
});
}
}
Future<double> get currentBrightness async {
try {
return await ScreenBrightness().current;
} catch (e) {
print(e);
throw 'Failed to get current brightness';
}
}
Future<void> setBrightness(double brightness) async {
try {
await ScreenBrightness().setScreenBrightness(brightness);
} catch (e) {
print(e);
throw 'Failed to set brightness';
}
}
@override
void dispose() {
_controller?.removeListener(() {});
_controller?.dispose();
if (isPressTimer != null) {
isPressTimer?.cancel();
isPressTimer = null;
}
if (EasyLoading.isShow) {
EasyLoading.dismiss();
}
super.dispose();
}
void _onVerticalDragStart(details) async {
_reset(context);
startPosition = details.globalPosition;
if (startPosition.dx < (layoutWidth / 2)) {
/// 左边触摸
// brightness = await Screen.brightness;
try {
brightness = await ScreenBrightness().current;
print("当前亮度${brightness.toString()}");
} catch (e) {
print('Failed to get current brightness');
}
brightnessOk = true;
}
}
void _onVerticalDragUpdate(details) {
if (!_controller!.value.isInitialized) {
return;
}
/// 累计计算偏移量(下滑减少百分比,上滑增加百分比)
movePan += (-details.delta.dy);
print(
"偏移量/整体高度${movePan.toString()}${(movePan / layoutHeight).toString()}");
if (startPosition.dx < (layoutWidth / 2)) {
/// 左边触摸
if (brightnessOk = true) {
setState(() {
volumePercentage = '亮度:${(_setBrightnessValue() * 100).toInt()}%';
print("现在的亮度和音量值${volumePercentage}");
showSettingDialog = false;
});
}
} else {
/// 右边触摸
setState(() {
volumePercentage = '音量:${(_setVerticalValue(num: 2) * 100).toInt()}%';
print("现在的亮度和音量值1${volumePercentage}");
showSettingDialog = false;
});
}
}
void _onVerticalDragEnd(_) async {
if (!_controller!.value.isInitialized) {
return;
}
if (startPosition.dx < (layoutWidth / 2)) {
if (brightnessOk) {
try {
await ScreenBrightness().setScreenBrightness(_setBrightnessValue());
} catch (e) {
print('Failed to set brightness');
}
brightnessOk = false;
// 左边触摸
setState(() {
showSettingDialog = true;
});
}
} else {
// 右边触摸
await _controller!.setVolume(_setVerticalValue());
setState(() {
showSettingDialog = true;
});
}
}
double _setBrightnessValue() {
// 亮度百分控制
double value =
//toStringAsFixed保留两位小数点
double.parse((movePan / layoutHeight + brightness).toStringAsFixed(2));
if (value >= 1.00) {
value = 1.00;
} else if (value <= 0.00) {
value = 0.00;
}
return value;
}
double _setVerticalValue({int num = 1}) {
// 声音亮度百分控制
double value = double.parse(
(movePan / layoutHeight + _controller!.value.volume)
.toStringAsFixed(num));
if (value >= 1.0) {
value = 1.0;
} else if (value <= 0.0) {
value = 0.0;
}
print("音量大小${value}");
return value;
}
void _reset(BuildContext context) {
startPosition = const Offset(0, 0);
movePan = 0;
layoutHeight = context.size!.height;
layoutWidth = context.size!.width;
volumePercentage = '';
}
void _onHorizontalDragStart(DragStartDetails details) async {
_reset(context);
if (!_controller!.value.isInitialized) {
return;
}
// 获取当前时间
position = _controller!.value.position;
// 暂停成功后才允许快进手势
allowHorizontal = true;
}
void _onHorizontalDragUpdate(DragUpdateDetails details) {
if (!_controller!.value.isInitialized && !allowHorizontal) {
return;
}
// 累计计算偏移量
movePan += details.delta.dx;
double value = _setHorizontalValue();
print("格式化秒数${value * _controller!.value.duration.inMilliseconds}");
// 用百分比计算出当前的秒数
String currentSecond = DateUtil.formatDateMs(
(value * _controller!.value.duration.inMilliseconds).toInt(),
format: 'mm:ss',
);
if (value >= 0) {
setState(() {
volumePercentage = '快进至:$currentSecond';
showSettingDialog = false;
});
} else {
setState(() {
volumePercentage = '快退至:${(value * 100).toInt()}%';
showSettingDialog = false;
});
}
}
void _onHorizontalDragEnd(DragEndDetails details) async {
if (!_controller!.value.isInitialized && !allowHorizontal) {
return;
}
double value = _setHorizontalValue();
int current = (value * _controller!.value.duration.inMilliseconds).toInt();
await _controller!.seekTo(Duration(milliseconds: current));
allowHorizontal = false;
setState(() {
showSettingDialog = true;
});
}
double _setHorizontalValue() {
// 进度条百分控制
double valueHorizontal =
double.parse((movePan / layoutWidth).toStringAsFixed(2));
// 当前进度条百分比
double currentValue =
position.inMilliseconds / _controller!.value.duration.inMilliseconds;
double value =
double.parse((currentValue + valueHorizontal).toStringAsFixed(2));
print(
"偏移量${movePan},偏移百分比${movePan / layoutWidth},进度条不知道什么参数${_controller!.value.duration.inMilliseconds}进度条百分比${position.inMilliseconds / _controller!.value.duration.inMilliseconds},value${value}");
if (value >= 1.00) {
value = 1.00;
} else if (value <= 0.00) {
value = 0.00;
}
return value;
}
@override
Widget build(BuildContext context) {
return Material(
child: _controller != null
? Container(
margin: EdgeInsets.only(top: Global.topHeight + 10),
color: Colors.grey,
child:
Column(mainAxisAlignment: MainAxisAlignment.start, children: [
if (!_controller!.value.isInitialized)
Stack(
alignment: Alignment.center,
children: [
Container(
height: 221,
width: Global.screenWidth,
color: Colors.black,
),
const SizedBox(
height: 30,
width: 30,
child: CircularProgressIndicator(
backgroundColor: Colors.white,
),
),
],
),
if (_controller!.value.isInitialized)
Stack(
alignment: Alignment.center,
children: [
Stack(
alignment: Alignment.center,
children: [
Stack(
alignment: Alignment.bottomCenter,
children: [
Stack(
alignment: Alignment.bottomCenter,
children: [
GestureDetector(
onVerticalDragStart: _onVerticalDragStart,
onVerticalDragUpdate: _onVerticalDragUpdate,
onVerticalDragEnd: _onVerticalDragEnd,
onHorizontalDragStart:
_onHorizontalDragStart,
onHorizontalDragUpdate:
_onHorizontalDragUpdate,
onHorizontalDragEnd: _onHorizontalDragEnd,
onLongPress: () {
_controller!.setPlaybackSpeed(2);
},
onLongPressUp: () {
_controller!.setPlaybackSpeed(1);
},
onDoubleTap: () {
_controller!.value.isPlaying
? _controller!.pause()
: _controller!.play();
},
onTap: () {
setState(() {
isPress = !isPress;
});
if (isPressTimer != null) {
isPressTimer?.cancel();
isPressTimer = null;
}
isPressTimer = Timer(
const Duration(milliseconds: 5000),
() {
setState(() {
isPress = false;
});
});
},
child: Container(
color: Colors.black,
alignment: Alignment.topCenter,
child: AspectRatio(
aspectRatio:
_controller!.value.aspectRatio,
child: VideoPlayer(_controller!))),
),
if (_controller!.value.isInitialized &&
isPress)
Row(
children: [
GestureDetector(
onTap: () {
_controller!.value.isPlaying
? _controller!.pause()
: _controller!.play();
},
child: Container(
padding: const EdgeInsets.only(
bottom: 5),
child: Icon(
_controller!.value.isPlaying
? Icons.pause
: Icons.play_arrow,
color: Colors.white,
size: 30,
),
),
),
Expanded(
child: Container(
padding:
const EdgeInsets.only(bottom: 5),
child: VideoProgressIndicator(
_controller!,
allowScrubbing: true,
colors: const VideoProgressColors(
backgroundColor: Colors.white24,
bufferedColor: Colors.white,
playedColor: Colors.pinkAccent),
),
)),
Container(
margin:
const EdgeInsets.only(left: 5),
child: Text(
"$cDuration/$tDuration",
style: const TextStyle(
color: Colors.white,
fontSize: 9),
),
),
GestureDetector(
onTap: () {
MyRouter.pushMy(
context,
MovieBigLandScape(
videoController:
_controller!));
},
child: Container(
padding: const EdgeInsets.only(
bottom: 5),
child: const Icon(
Icons.play_arrow,
color: Colors.white,
size: 30,
),
),
),
],
),
],
),
if (!isPress)
VideoProgressIndicator(
_controller!,
allowScrubbing: true,
colors: const VideoProgressColors(
backgroundColor: Colors.white24,
bufferedColor: Colors.white,
playedColor: Colors.pinkAccent),
)
],
),
if (isBuffer)
const SizedBox(
height: 30,
width: 30,
child: CircularProgressIndicator(
backgroundColor: Colors.white,
),
)
],
),
Offstage(
offstage: showSettingDialog,
child: Container(
decoration: const BoxDecoration(color: Colors.white),
padding: const EdgeInsets.only(
left: 5, right: 5, top: 2, bottom: 2),
child: Text(
volumePercentage,
style: const TextStyle(
color: Colors.black, fontSize: 15),
),
),
)
],
),
]),
)
: Container(),
);
}
}
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';
import '../../router.dart';
class MovieBigLandScape extends StatefulWidget {
//参数传递定义
final VideoPlayerController videoController;
const MovieBigLandScape({Key? key, required this.videoController})
: super(key: key);
@override
State<StatefulWidget> createState() => MovieBigLandScapeState();
}
class MovieBigLandScapeState extends State<MovieBigLandScape> {
bool isPress = false;
late Timer? isPressTimer;
//获取当前视频播放的信息
late VideoPlayerValue videoPlayerValue;
//当前播放视频的总时长
late Duration totalDuration;
//当前播放视频的位置
late Duration currentDuration;
String tDuration = "0:00:00";
String cDuration = "0:00:00";
//当前视频是否缓存
bool isBuffer = false;
@override
void initState() {
isPressTimer = Timer(const Duration(), () {});
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft, //全屏时旋转方向,左边
]);
widget.videoController.addListener(() {
mySetState(() {
videoPlayerValue = widget.videoController.value;
totalDuration = videoPlayerValue.duration;
currentDuration = videoPlayerValue.position;
tDuration = totalDuration.toString().substring(0, 7);
cDuration = currentDuration.toString().substring(0, 7);
isBuffer = videoPlayerValue.isBuffering;
});
});
super.initState();
}
mySetState(callBack) {
if (mounted) {
setState(() {
callBack();
});
}
}
@override
void dispose() {
if (isPressTimer != null) {
isPressTimer?.cancel();
isPressTimer = null;
}
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Material(
child: Stack(
alignment: Alignment.center,
children: [
Stack(
alignment: Alignment.bottomCenter,
children: [
Stack(
alignment: Alignment.bottomCenter,
children: [
GestureDetector(
onDoubleTap: () {
widget.videoController.value.isPlaying
? widget.videoController.pause()
: widget.videoController.play();
},
onLongPress: (){
widget.videoController.setPlaybackSpeed(2);
},
onLongPressUp: (){
widget.videoController.setPlaybackSpeed(1);
},
onTap: () {
setState(() {
isPress = !isPress;
});
if (isPressTimer != null) {
isPressTimer?.cancel();
isPressTimer = null;
}
isPressTimer =
Timer(const Duration(milliseconds: 5000), () {
setState(() {
isPress = false;
});
});
},
child: Container(
color: Colors.black,
alignment: Alignment.topCenter,
child: AspectRatio(
aspectRatio:
widget.videoController.value.aspectRatio,
child: VideoPlayer(widget.videoController))),
),
if (isPress)
Row(
children: [
GestureDetector(
onTap: () {
widget.videoController.value.isPlaying
? widget.videoController.pause()
: widget.videoController.play();
},
child: Container(
padding: const EdgeInsets.only(bottom: 5),
child: Icon(
widget.videoController.value.isPlaying
? Icons.pause
: Icons.play_arrow,
color: Colors.white,
size: 30,
),
),
),
Expanded(
child: Container(
padding: const EdgeInsets.only(bottom: 5),
child: VideoProgressIndicator(
widget.videoController,
allowScrubbing: true,
colors: const VideoProgressColors(
backgroundColor: Colors.white24,
bufferedColor: Colors.white,
playedColor: Colors.pinkAccent),
),
)),
Container(
margin: const EdgeInsets.only(left: 5),
child: Text(
"$cDuration/$tDuration",
style: const TextStyle(
color: Colors.white, fontSize: 9),
),
),
GestureDetector(
onTap: () {
MyRouter.pop(context);
},
child: Container(
padding: const EdgeInsets.only(bottom: 5),
child: const Icon(
Icons.play_arrow,
color: Colors.white,
size: 30,
),
),
),
],
),
],
),
if (!isPress)
VideoProgressIndicator(
widget.videoController,
allowScrubbing: true,
colors: const VideoProgressColors(
backgroundColor: Colors.white24,
bufferedColor: Colors.white,
playedColor: Colors.pinkAccent),
)
],
),
if (isBuffer)
const SizedBox(
height: 30,
width: 30,
child: CircularProgressIndicator(
backgroundColor: Colors.white,
),
)
],
),
);
}
}
相关文章
- Flutter快速开发——列表分页加载封装
- Flutter 使用插件打开相册、相机「建议收藏」
- Flutter 本地数据库sqflite实战操作「建议收藏」
- 【Flutter桌面篇】Flutter&Windows应用尝鲜
- 【Flutter&Flame 游戏 - 伍】 Canvas 参上 | 角色的血条
- Flutter 组件集录 | 桌面导航 NavigationRail
- flutter 自定义播放器进度条
- 为什么flutter可以跨平台
- Flutter 3.3更新详解
- Flutter 下载篇 - 贰 | 当下载器遇上网络库切换
- 不得不知道的Flutter异常捕获知识点:Zone
- flutter系列之:在flutter中使用导航Navigator
- 一天搞定:Flutter + ChatGPT,打造智能聊天机器人
- 【错误记录】Flutter 报错 ( Could not read script ‘xxxflutter_toolsgradleapp_plugin_loader.gradle‘ )
- 【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )
- 【Flutter】FutureBuilder 异步编程 ( FutureBuilder 构造方法 | AsyncSnapshot 异步计算 )
- 【Flutter】ListView 列表高级功能 ( RefreshIndicator 下拉刷新组件 )
- Flutter 后台任务
- 使用 Flutter 创建 App