flutter視訊全頻播放,音量亮度的調節
flutter本地視訊播放
第一次寫部落格不知道該怎麼寫,對於flutter我也是新手,所以程式碼還有很多地方完善,但是主要的功能都已經有了,視訊全頻播放,音量亮度的調節的功能都有了。有需要的朋友可以直接複製。
import ‘dart:async’;
import ‘package:auto_orientation/auto_orientation.dart’;
import ‘package:common_utils/common_utils.dart’;
import ‘package:flutter/material.dart’;
import ‘package:flutter/services.dart’;
import ‘package:flutter_screenutil/flutter_screenutil.dart’;
import ‘package:screen/screen.dart’;
import ‘package:volume_control/volume_control.dart’;
import ‘package:video_player/video_player.dart’;
class Player extends StatefulWidget {
@override
VideoPlay createState() =>
// TODO: implement createState
VideoPlay();
}
// initialize() - 初始化播放器。
// dispose() - 釋放播放器資源。
// notifyListeners() - 監聽播放訊息。
// addListener(listener) - 新增監聽器。
// removeListener(listener) - 移除監聽器。
// pause() - 暫停播放。
// play() - 開始播放。
// position - 播放位置。
// seekTo(moment) - 指定到某個位置播放。
// setLooping(looping) - 是否迴圈播放。
// setVolume(volume) - 設定音量大小。
class VideoPlay extends State {
VideoPlayerController _controller;
String Url = ‘https://www.runoob.com/try/demo_source/mov_bbb.mp4’;
bool _isPlaying = false;
Timer _timer; // 計時器,用於延遲隱藏控制元件ui
bool _hidePlayControl = false; // 控制是否隱藏控制元件ui
double _playControlOpacity = 1; // 通過透明度動畫顯示/隱藏控制元件ui
// 記錄video播放進度
// Duration _position = Duration(seconds: 0);
// Duration _totalDuration = Duration(seconds: 0);
double value = 00.00;
int num = 0;
double progressValue; //進度
String labelProgress; //tip內容
bool handle = false; //判斷是否在滑動的標識
bool _hideText = true; // 控制是否隱藏文字
Offset startPosition; // 起始位置
double movePan; // 偏移量累計總和
double layoutWidth; // 元件寬度
double layoutHeight; // 元件高度
String volumePercentage = ‘’; // 元件位移描述
double playDialogOpacity = 0.0;
double brightness = 0.0; //亮度
double voice = 0.0; //聲音
bool brightnessOk = false; // 是否允許調節亮度
/// 記錄是否全屏
bool get _isFullScreen =>
MediaQuery.of(context).orientation == Orientation.landscape;
// 攔截返回鍵
Future _onWillPop() async {
if (_isFullScreen) {
_toggleFullScreen();
return false;
}
return true;
}
// 供父元件呼叫重新整理頁面,減少父元件的build
// void setPosition({position, totalDuration}) {
// setState(() {
// _position = position;
// _totalDuration = totalDuration;
// });
// }
///重新整理資料
void reloadData({double ProgressValue, String LabelProgress}) {
if (mounted) {
setState(() {
// if (ProgressValue == 00.00 && LabelProgress == “00.00”) {
// _controller.play();
// }
progressValue = ProgressValue;
labelProgress = LabelProgress;
});
}
}
@override
void initState() {
//重寫元件初始化方法
super.initState();
progressValue = 00.00;
labelProgress = '00:00';
// VideoPlayerUI.network, VideoPlayerUI.asset, VideoPlayerUI.file,網路視訊、工程視訊、本地視訊檔案
_controller =
VideoPlayerController.asset(
'assets/video/mov_bbb.mp4') //10026 31138
// VideoPlayerController.network(//定義聯結器內容,
// 'http://vfx.mtime.cn/Video/2019/03/21/mp4/190321153853126488.mp4')//99963
..addListener(() {
int duration = _controller.value.duration.inMilliseconds;
int position = _controller.value.position.inMilliseconds;
progressValue = position / duration * 100;
labelProgress =
_controller.value.position.toString().substring(2).split(".")[0];
reloadData(ProgressValue: progressValue, LabelProgress: labelProgress);//實時重新整理資料
final bool isPlaying = _controller.value.isPlaying;
if (isPlaying != _isPlaying) {
setState(() {
_isPlaying = isPlaying;
});
}
})
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {
// _controller.play();
});
});
// ..setLooping(true);//迴圈播放
// _startPlayControlTimer();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
// appBar: AppBar(
// title: Text(“視訊播放器”),
// ),
body: Container(
width: 10.wp,
child: _controller.value.initialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: Stack(
children: [
GestureDetector(
child: VideoPlayer(_controller),
onTap: _togglePlayControl,
onVerticalDragStart: _onVerticalDragStart,
//指標已經接觸到螢幕,而且可能開始垂直移動。
onVerticalDragUpdate:
_onVerticalDragUpdate, //與螢幕接觸並垂直移動的指標沿垂直方向移動
),
Offstage(
offstage: _hideText,
child: Center(
child: AnimatedOpacity(
opacity: playDialogOpacity,
duration: Duration(milliseconds: 500),
child: Container(
padding: EdgeInsets.symmetric(
vertical: 5.0, horizontal: 6.0),
decoration: BoxDecoration(
color: Colors.black87,
borderRadius:
BorderRadius.all(Radius.circular(5.0))),
child: Text(
volumePercentage,
style: TextStyle(
color: Colors.white, fontSize: 12),
),
),
),
)),
Positioned(
bottom: 0,
child: WillPopScope(
onWillPop: _onWillPop,
child: Offstage(
offstage: _hidePlayControl,
child: AnimatedOpacity(
// 加入透明度動畫
opacity: _playControlOpacity,
duration: Duration(milliseconds: 300),
child: Row(
// 載入完成時才渲染,flex佈局
children: [
IconButton(
// 播放按鈕
padding: EdgeInsets.zero,
iconSize: 26,
icon: Icon(
// 根據控制器動態變化播放圖示還是暫停
_controller.value.isPlaying
? Icons.pause
: Icons.play_arrow,
color: Colors.white,
),
onPressed: () {
setState(() {
_playOrPause();
});
},
),
SizedBox(
width: !_isFullScreen ? 0.5.wp : 1.5.wp,
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
//已拖動的顏色
activeTrackColor: Colors.blue,
//未拖動的顏色
inactiveTrackColor: Colors.white,
overlayShape: RoundSliderOverlayShape(
//可繼承SliderComponentShape自定義形狀
overlayRadius: 10, //滑塊外圈大小
),
thumbShape: RoundSliderThumbShape(
//可繼承SliderComponentShape自定義形狀
disabledThumbRadius: 7, //禁用是滑塊大小
enabledThumbRadius: 7, //滑塊大小
)),
child: Slider(
value: progressValue,
// label: labelProgress,
divisions: 100,
onChangeStart: _onChangeStart,
onChangeEnd: _onChangeEnd,
onChanged: (val) {
int duration = _controller
.value.duration.inMilliseconds;
setState(() {
progressValue =
val.floorToDouble(); //轉化成double
labelProgress = DateUtil.formatDateMs(
(val / 100 * duration).toInt(),
format: ‘mm:ss’,
);
});
},
min: 0.0,
max: 100,
),
),
),
Container(
// 播放時間
margin: EdgeInsets.only(left: 10),
child: Text(
labelProgress +
"/" +
// _controller.value.duration.inMilliseconds
DateUtil.formatDateMs(
(_controller.value.duration
.inMilliseconds)
.toInt(),
format: 'mm:ss',
),
style: TextStyle(color: Colors.white),
),
),
IconButton(
// 全屏/橫屏按鈕
padding: EdgeInsets.zero,
iconSize: 26,
icon: Icon(
// 根據當前螢幕方向切換圖示
_isFullScreen
? Icons.fullscreen_exit
: Icons.fullscreen,
color: Colors.white,
),
onPressed: () {
// 點選切換是否全屏
_toggleFullScreen();
},
),
],
),
),
),
),
),
],
))
: Container(),
),
);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
brightnessOk = false;
// allowHorizontal = false;
}
void _playOrPause() {
/// 同樣的,點選動態播放或者暫停
// int duration = _controller.value.duration.inMilliseconds;
// int position = _controller.value.position.inMilliseconds;
// duration == position ? _replay():
_controller.value.isPlaying ? _controller.pause() : _controller.play();
_startPlayControlTimer(); // 操作控制元件後,重置延遲隱藏控制元件的timer
}
//重播
// void _replay() {
//
// super.initState();
// initState();
// }
@override
void _toggleFullScreen() {
setState(() {
if (_isFullScreen) {
/// 如果是全屏就切換豎屏
// _controller.pause();
AutoOrientation.portraitAutoMode();
///顯示狀態列,與底部虛擬操作按鈕
SystemChrome.setEnabledSystemUIOverlays(
[SystemUiOverlay.top, SystemUiOverlay.bottom]);
} else {
// _controller.play();
AutoOrientation.landscapeAutoMode();
///關閉狀態列,與底部虛擬操作按鈕
SystemChrome.setEnabledSystemUIOverlays([]);
}
_startPlayControlTimer(); // 操作完控制元件開始計時隱藏
});
}
void backPress() {
// 如果是全屏,點選返回鍵則關閉全屏,如果不是,則系統返回鍵
if (_isFullScreen) {
_toggleFullScreen();
} else if (ModalRoute.of(context).isFirst) {
SystemNavigator.pop();
} else {
Navigator.pop(context);
}
}
void onChangeStart() {
// 開始手動操作標識
handle = true;
}
void onChangeEnd() {
// if (!videoInit) {
// return;
// }
// widget.startPlayControlTimer();
// 關閉手動操作標識
handle = false;
// 跳轉到滑動時間
int duration = _controller.value.duration.inMilliseconds;
_controller.seekTo(
Duration(milliseconds: (progressValue / 100 * duration).toInt()),
);
if (!_controller.value.isPlaying) {
_controller.play();
}
}
///狀態列隱藏
void _startPlayControlTimer() {
/// 計時器,用法和前端js的大同小異
if (_timer != null) _timer.cancel();
_timer = Timer(
Duration(seconds: 3),
() {
/// 延遲3s後隱藏
setState(() {
_playControlOpacity = 0;
Future.delayed(Duration(milliseconds: 500)).whenComplete(() {
_hidePlayControl = true;
});
});
},
);
// _timer = Timer(Duration(seconds: 1), () {
// /// 延遲3s後隱藏
// setState(() {
// playDialogOpacity = 0.0;
// Future.delayed(Duration(milliseconds: 500)).whenComplete(() {
// _hideText = true;
// });
// });
// });
}
///音量和亮度隱藏
void _startTimer() {
/// 計時器,用法和前端js的大同小異
if (_timer != null) _timer.cancel();
_timer = Timer(Duration(seconds: 1), () {
/// 延遲3s後隱藏
setState(() {
playDialogOpacity = 0.0;
Future.delayed(Duration(milliseconds: 500)).whenComplete(() {
_hideText = true;
});
});
});
}
void _togglePlayControl() {
setState(() {
num++;
///雙擊暫停或者播放
if (num % 2 == 0) {
if (_controller.value.isPlaying) {
_controller.pause();
} else {
_controller.play();
}
}
if (_hidePlayControl) {
/// 如果隱藏則顯示
_hidePlayControl = false;
_playControlOpacity = 1;
_startPlayControlTimer(); // 開始計時器,計時後隱藏
} else {
/// 如果顯示就隱藏
if (_timer != null) _timer.cancel(); // 有計時器先移除計時器
_playControlOpacity = 0;
playDialogOpacity = 0.0;
Future.delayed(Duration(milliseconds: 500)).whenComplete(() {
_hidePlayControl = true; // 延遲500ms(透明度動畫結束)後,隱藏
_hideText = true;
});
}
});
}
void _reset(BuildContext context) {
startPosition = Offset(0, 0);
movePan = 0;
layoutHeight = context.size.height;
layoutWidth = context.size.width;
volumePercentage = ‘’;
}
void _onVerticalDragStart(details) async {
_reset(context);
startPosition = details.globalPosition;
if (startPosition.dx < (layoutWidth / 2)) {
/// 左邊觸控
brightnessOk = true;
brightness = await Screen.brightness;
} else {
voice = await VolumeControl.volume;
print(voice);
}
}
void _onVerticalDragUpdate(details) {
// if (!videoInit) {
// return;
// }
/// 累計計算偏移量(下滑減少百分比,上滑增加百分比)
movePan += (-details.delta.dy);
if (startPosition.dx < (layoutWidth / 2)) {
/// 左邊觸控
if (brightnessOk = true) {
setState(() {
volumePercentage = '亮度:${(_setBrightnessValue() * 100).toInt()}%';
_hideText = false;
playDialogOpacity = 1.0;
// 設定亮度:
});
}
} else {
/// 右邊觸控
setState(() {
volumePercentage = '音量:${(_setVerticalValue(num: 2) * 100).toInt()}%';
_hideText = false;
playDialogOpacity = 1.0;
});
}
_startTimer();
}
double _setVerticalValue({int num = 1}) {
// 聲音百分控制
double value =
double.parse((movePan / layoutHeight + voice) //_controller.value.volume
.toStringAsFixed(num));
if (value >= 1.0) {
value = 1.0;
} else if (value <= 0.0) {
value = 0.0;
}
VolumeControl.setVolume(value);
return value;
}
double _setBrightnessValue() {
// 亮度百分控制
double value =
double.parse((movePan / layoutHeight + brightness).toStringAsFixed(2));
if (value >= 1.00) {
value = 1.00;
} else if (value <= 0.00) {
value = 0.00;
}
Screen.setBrightness(value);
return value;
}
}
相關文章
- 萬彩動畫大師教程 | 對新增的視訊進行音量的調節動畫
- win10為什麼不能調節亮度 win10調節亮度的方法Win10
- iOS 調節系統音量iOS
- win10螢幕亮度怎麼調節 win10螢幕亮度調節的方法Win10
- windows10調節螢幕亮度怎麼操作_windows10亮度調節在哪Windows
- android開發之GestureDetector手勢識別(調節音量、亮度、快進和後退)Android
- Flutter視訊播放封裝歷程Flutter封裝
- 電腦亮度怎麼調亮度按哪個鍵 電腦亮度調節操作方法
- android4.4調整音量調節速度Android
- Mac怎麼調節螢幕亮度Mac
- SoundSpot Evade for Mac音量調節器Mac
- Mac新手使用技巧——Mac音量調節Mac
- 瘋殼Android嵌入式Linux平板開發教程3-4亮度及音量調節AndroidLinux
- Windows10無法調節音量怎麼辦 win10音量無法調節如何解決WindowsWin10
- 釋出一個方便調節主音量和Wave音量的小程式
- win10亮度不能調節的如何修復_win10亮度調節失靈的最佳解決方法Win10
- 榮耀手機自動調節亮度怎麼關閉?榮耀手機關閉調節自動亮度教程
- win10螢幕亮度低怎麼調節 臺式win10調節亮度低操作方法Win10
- 如何實現視訊加密全平臺播放加密
- 分享一個功能很全的視訊播放器播放器
- win10螢幕亮度不能調節調節無效怎麼辦Win10
- win10亮度調節沒了怎麼辦_win10沒有亮度調節選項恢復方法Win10
- 一個高自由度的Flutter 視訊播放器Flutter播放器
- win10螢幕亮度無法調節?一招解決Win10電腦亮度調節失靈Win10
- 電腦倍速播放視訊不變調的軟體下載 | 手機倍速播放視訊最好的軟體(不變調且可以記憶倍速播放效果)
- 同時剪輯多個視訊,批量調整多個視訊的播放速度
- win7音訊 audio service調節單個程式音量控制Win7音訊
- 蘋果ios10怎麼調手電筒亮度 ios10手電筒亮度調節方法蘋果iOS
- 【.NET 與樹莓派】PWM 調節LED小燈的亮度樹莓派
- Flutter 實現視訊全屏播放邏輯及解析Flutter
- 使用flutter編寫一款視訊播放軟體Flutter
- koo視訊播放器整合到flutter專案中播放器Flutter
- Flutter(十) 音訊+影片播放Flutter音訊
- 教你如何給視訊批量調整播放速度,將視訊同時減速
- 視音訊播放音訊
- opencv視訊播放OpenCV
- 影片:Type Cover鍵盤調節Surface Pro 3亮度演示
- iOS 圖解一個功能很全的視訊播放器的使用iOS圖解播放器