video: added seek by tap/drag on progress bar

This commit is contained in:
Thibault Deckers 2019-10-06 17:15:20 +09:00
parent b4c04d0cdf
commit 831a787ed6
3 changed files with 65 additions and 60 deletions

View file

@ -27,6 +27,9 @@ class VideoControlOverlay extends StatefulWidget {
} }
class VideoControlOverlayState extends State<VideoControlOverlay> { class VideoControlOverlayState extends State<VideoControlOverlay> {
final GlobalKey _progressBarKey = GlobalKey();
bool _playingOnDragStart = false;
ImageEntry get entry => widget.entry; ImageEntry get entry => widget.entry;
Animation<double> get scale => widget.scale; Animation<double> get scale => widget.scale;
@ -67,7 +70,6 @@ class VideoControlOverlayState extends State<VideoControlOverlay> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final progressBarBorderRadius = 123.0;
final mediaQuery = MediaQuery.of(context); final mediaQuery = MediaQuery.of(context);
final viewInsets = widget.viewInsets ?? mediaQuery.viewInsets; final viewInsets = widget.viewInsets ?? mediaQuery.viewInsets;
final viewPadding = widget.viewPadding ?? mediaQuery.viewPadding; final viewPadding = widget.viewPadding ?? mediaQuery.viewPadding;
@ -87,6 +89,10 @@ class VideoControlOverlayState extends State<VideoControlOverlay> {
width: mediaQuery.size.width - safePadding.horizontal, width: mediaQuery.size.width - safePadding.horizontal,
child: Row( child: Row(
children: [ children: [
Expanded(
child: _buildProgressBar(),
),
SizedBox(width: 8),
OverlayButton( OverlayButton(
scale: scale, scale: scale,
child: value.isPlaying child: value.isPlaying
@ -101,52 +107,62 @@ class VideoControlOverlayState extends State<VideoControlOverlay> {
tooltip: 'Play', tooltip: 'Play',
), ),
), ),
SizedBox(width: 8),
Expanded(
child: SizeTransition(
sizeFactor: scale,
child: BlurredRRect(
borderRadius: progressBarBorderRadius,
child: Container(
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 16) + EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.black26,
border: Border.all(color: Colors.white30, width: 0.5),
borderRadius: BorderRadius.all(
Radius.circular(progressBarBorderRadius),
),
),
child: Column(
children: [
Row(
children: [
Text(formatDuration(value.position ?? Duration.zero)),
Spacer(),
Text(formatDuration(value.duration ?? Duration.zero)),
],
),
LinearProgressIndicator(value: progress),
],
),
),
),
),
),
SizedBox(width: 8),
OverlayButton(
scale: scale,
child: IconButton(
icon: Icon(Icons.fullscreen),
onPressed: () => _goFullscreen(),
tooltip: 'Fullscreen',
),
),
], ],
), ),
), ),
); );
} }
SizeTransition _buildProgressBar() {
final progressBarBorderRadius = 123.0;
return SizeTransition(
sizeFactor: scale,
child: BlurredRRect(
borderRadius: progressBarBorderRadius,
child: GestureDetector(
onTapDown: (TapDownDetails details) {
_seek(details.globalPosition);
},
onHorizontalDragStart: (DragStartDetails details) {
_playingOnDragStart = controller.value.isPlaying;
if (_playingOnDragStart) controller.pause();
},
onHorizontalDragUpdate: (DragUpdateDetails details) {
_seek(details.globalPosition);
},
onHorizontalDragEnd: (DragEndDetails details) {
if (_playingOnDragStart) controller.play();
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 16) + EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.black26,
border: Border.all(color: Colors.white30, width: 0.5),
borderRadius: BorderRadius.all(
Radius.circular(progressBarBorderRadius),
),
),
child: Column(
key: _progressBarKey,
children: [
Row(
children: [
Text(formatDuration(value.position ?? Duration.zero)),
Spacer(),
Text(formatDuration(value.duration ?? Duration.zero)),
],
),
LinearProgressIndicator(value: progress),
],
),
),
),
),
);
}
_onValueChange() => setState(() {});
_playPause() async { _playPause() async {
if (value.isPlaying) { if (value.isPlaying) {
controller.pause(); controller.pause();
@ -159,7 +175,10 @@ class VideoControlOverlayState extends State<VideoControlOverlay> {
setState(() {}); setState(() {});
} }
_goFullscreen() {} _seek(Offset globalPosition) {
final keyContext = _progressBarKey.currentContext;
_onValueChange() => setState(() {}); final RenderBox box = keyContext.findRenderObject();
final localPosition = box.globalToLocal(globalPosition);
controller.seekTo(value.duration * (localPosition.dx / box.size.width));
}
} }

View file

@ -36,13 +36,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.2" version: "1.1.2"
chewie:
dependency: "direct main"
description:
name: chewie
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.7"
collection: collection:
dependency: "direct main" dependency: "direct main"
description: description:
@ -148,13 +141,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.6" version: "1.1.6"
open_iconic_flutter:
dependency: transitive
description:
name: open_iconic_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
path: path:
dependency: "direct main" dependency: "direct main"
description: description:
@ -336,7 +322,7 @@ packages:
source: hosted source: hosted
version: "2.0.8" version: "2.0.8"
video_player: video_player:
dependency: transitive dependency: "direct main"
description: description:
name: video_player name: video_player
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"

View file

@ -16,7 +16,6 @@ version: 1.0.0+1
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
chewie: 0.9.7
collection: collection:
draggable_scrollbar: draggable_scrollbar:
git: git:
@ -40,6 +39,7 @@ dependencies:
sqflite: sqflite:
transparent_image: transparent_image:
tuple: tuple:
video_player:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: