Skip to content

Commit cd41237

Browse files
committed
Make swipe down to exit fullscreen an option
1 parent a4d847b commit cd41237

File tree

1 file changed

+66
-70
lines changed

1 file changed

+66
-70
lines changed

lib/src/chewie_player.dart

Lines changed: 66 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ import 'package:provider/provider.dart';
1313
import 'package:video_player/video_player.dart';
1414
import 'package:wakelock_plus/wakelock_plus.dart';
1515

16-
typedef ChewieRoutePageBuilder =
17-
Widget Function(
18-
BuildContext context,
19-
Animation<double> animation,
20-
Animation<double> secondaryAnimation,
21-
ChewieControllerProvider controllerProvider,
22-
);
16+
typedef ChewieRoutePageBuilder = Widget Function(
17+
BuildContext context,
18+
Animation<double> animation,
19+
Animation<double> secondaryAnimation,
20+
ChewieControllerProvider controllerProvider,
21+
);
2322

2423
/// A Video Player with Material and Cupertino skins.
2524
///
@@ -72,8 +71,7 @@ class ChewieState extends State<Chewie> {
7271

7372
Future<void> listener() async {
7473
if (isControllerFullScreen && !_isFullScreen) {
75-
_wasPlayingBeforeFullScreen =
76-
widget.controller.videoPlayerController.value.isPlaying;
74+
_wasPlayingBeforeFullScreen = widget.controller.videoPlayerController.value.isPlaying;
7775
_resumeAppliedInFullScreen = false;
7876
_isFullScreen = isControllerFullScreen;
7977
await _pushFullScreenWidget(context);
@@ -104,20 +102,26 @@ class ChewieState extends State<Chewie> {
104102
) {
105103
return Scaffold(
106104
resizeToAvoidBottomInset: false,
107-
body: GestureDetector(
108-
onVerticalDragEnd: (DragEndDetails details) {
109-
// A positive dy indicates a downward swipe. Use a threshold to avoid accidental triggers.
110-
final double dy = details.primaryVelocity ?? 0;
111-
if (dy > 300) {
112-
widget.controller.exitFullScreen();
113-
}
114-
},
115-
child: Container(
116-
alignment: Alignment.center,
117-
color: Colors.black,
118-
child: controllerProvider,
119-
),
120-
),
105+
body: widget.controller.swipeToExitFullscreen
106+
? GestureDetector(
107+
onVerticalDragEnd: (DragEndDetails details) {
108+
// A positive dy indicates a downward swipe. Use a threshold to avoid accidental triggers.
109+
final double dy = details.primaryVelocity ?? 0;
110+
if (dy > widget.controller.swipeThreshold) {
111+
widget.controller.exitFullScreen();
112+
}
113+
},
114+
child: Container(
115+
alignment: Alignment.center,
116+
color: Colors.black,
117+
child: controllerProvider,
118+
),
119+
)
120+
: Container(
121+
alignment: Alignment.center,
122+
color: Colors.black,
123+
child: controllerProvider,
124+
),
121125
);
122126
}
123127

@@ -220,8 +224,7 @@ class ChewieState extends State<Chewie> {
220224

221225
void onEnterFullScreen() {
222226
final videoWidth = widget.controller.videoPlayerController.value.size.width;
223-
final videoHeight =
224-
widget.controller.videoPlayerController.value.size.height;
227+
final videoHeight = widget.controller.videoPlayerController.value.size.height;
225228

226229
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
227230

@@ -253,13 +256,15 @@ class ChewieState extends State<Chewie> {
253256
DeviceOrientation.landscapeRight,
254257
]);
255258
}
259+
256260
/// Video h > w means we force portrait
257261
else if (isPortraitVideo) {
258262
SystemChrome.setPreferredOrientations([
259263
DeviceOrientation.portraitUp,
260264
DeviceOrientation.portraitDown,
261265
]);
262266
}
267+
263268
/// Otherwise if h == w (square video)
264269
else {
265270
SystemChrome.setPreferredOrientations(DeviceOrientation.values);
@@ -344,10 +349,12 @@ class ChewieController extends ChangeNotifier {
344349
this.hideControlsTimer = defaultHideControlsTimer,
345350
this.controlsSafeAreaMinimum = EdgeInsets.zero,
346351
this.pauseOnBackgroundTap = false,
352+
this.swipeToExitFullscreen = true,
353+
this.swipeThreshold = 300,
347354
}) : assert(
348-
playbackSpeeds.every((speed) => speed > 0),
349-
'The playbackSpeeds values must all be greater than 0',
350-
) {
355+
playbackSpeeds.every((speed) => speed > 0),
356+
'The playbackSpeeds values must all be greater than 0',
357+
) {
351358
_initialize();
352359
}
353360

@@ -400,39 +407,32 @@ class ChewieController extends ChangeNotifier {
400407
Animation<double>,
401408
Animation<double>,
402409
ChewieControllerProvider,
403-
)?
404-
routePageBuilder,
410+
)? routePageBuilder,
405411
bool? pauseOnBackgroundTap,
412+
bool? swipeToExitFullscreen,
413+
double? swipeThreshold,
406414
}) {
407415
return ChewieController(
408416
draggableProgressBar: draggableProgressBar ?? this.draggableProgressBar,
409-
videoPlayerController:
410-
videoPlayerController ?? this.videoPlayerController,
417+
videoPlayerController: videoPlayerController ?? this.videoPlayerController,
411418
optionsTranslation: optionsTranslation ?? this.optionsTranslation,
412419
aspectRatio: aspectRatio ?? this.aspectRatio,
413420
autoInitialize: autoInitialize ?? this.autoInitialize,
414421
autoPlay: autoPlay ?? this.autoPlay,
415422
startAt: startAt ?? this.startAt,
416423
looping: looping ?? this.looping,
417424
fullScreenByDefault: fullScreenByDefault ?? this.fullScreenByDefault,
418-
cupertinoProgressColors:
419-
cupertinoProgressColors ?? this.cupertinoProgressColors,
420-
materialProgressColors:
421-
materialProgressColors ?? this.materialProgressColors,
425+
cupertinoProgressColors: cupertinoProgressColors ?? this.cupertinoProgressColors,
426+
materialProgressColors: materialProgressColors ?? this.materialProgressColors,
422427
zoomAndPan: zoomAndPan ?? this.zoomAndPan,
423428
maxScale: maxScale ?? this.maxScale,
424-
controlsSafeAreaMinimum:
425-
controlsSafeAreaMinimum ?? this.controlsSafeAreaMinimum,
426-
transformationController:
427-
transformationController ?? this.transformationController,
428-
materialSeekButtonFadeDuration:
429-
materialSeekButtonFadeDuration ?? this.materialSeekButtonFadeDuration,
430-
materialSeekButtonSize:
431-
materialSeekButtonSize ?? this.materialSeekButtonSize,
429+
controlsSafeAreaMinimum: controlsSafeAreaMinimum ?? this.controlsSafeAreaMinimum,
430+
transformationController: transformationController ?? this.transformationController,
431+
materialSeekButtonFadeDuration: materialSeekButtonFadeDuration ?? this.materialSeekButtonFadeDuration,
432+
materialSeekButtonSize: materialSeekButtonSize ?? this.materialSeekButtonSize,
432433
placeholder: placeholder ?? this.placeholder,
433434
overlay: overlay ?? this.overlay,
434-
showControlsOnInitialize:
435-
showControlsOnInitialize ?? this.showControlsOnInitialize,
435+
showControlsOnInitialize: showControlsOnInitialize ?? this.showControlsOnInitialize,
436436
showOptions: showOptions ?? this.showOptions,
437437
optionsBuilder: optionsBuilder ?? this.optionsBuilder,
438438
additionalOptions: additionalOptions ?? this.additionalOptions,
@@ -447,26 +447,20 @@ class ChewieController extends ChangeNotifier {
447447
isLive: isLive ?? this.isLive,
448448
allowFullScreen: allowFullScreen ?? this.allowFullScreen,
449449
allowMuting: allowMuting ?? this.allowMuting,
450-
allowPlaybackSpeedChanging:
451-
allowPlaybackSpeedChanging ?? this.allowPlaybackSpeedChanging,
450+
allowPlaybackSpeedChanging: allowPlaybackSpeedChanging ?? this.allowPlaybackSpeedChanging,
452451
useRootNavigator: useRootNavigator ?? this.useRootNavigator,
453452
playbackSpeeds: playbackSpeeds ?? this.playbackSpeeds,
454-
systemOverlaysOnEnterFullScreen:
455-
systemOverlaysOnEnterFullScreen ??
456-
this.systemOverlaysOnEnterFullScreen,
453+
systemOverlaysOnEnterFullScreen: systemOverlaysOnEnterFullScreen ?? this.systemOverlaysOnEnterFullScreen,
457454
deviceOrientationsOnEnterFullScreen:
458-
deviceOrientationsOnEnterFullScreen ??
459-
this.deviceOrientationsOnEnterFullScreen,
460-
systemOverlaysAfterFullScreen:
461-
systemOverlaysAfterFullScreen ?? this.systemOverlaysAfterFullScreen,
462-
deviceOrientationsAfterFullScreen:
463-
deviceOrientationsAfterFullScreen ??
464-
this.deviceOrientationsAfterFullScreen,
455+
deviceOrientationsOnEnterFullScreen ?? this.deviceOrientationsOnEnterFullScreen,
456+
systemOverlaysAfterFullScreen: systemOverlaysAfterFullScreen ?? this.systemOverlaysAfterFullScreen,
457+
deviceOrientationsAfterFullScreen: deviceOrientationsAfterFullScreen ?? this.deviceOrientationsAfterFullScreen,
465458
routePageBuilder: routePageBuilder ?? this.routePageBuilder,
466459
hideControlsTimer: hideControlsTimer ?? this.hideControlsTimer,
467-
progressIndicatorDelay:
468-
progressIndicatorDelay ?? this.progressIndicatorDelay,
460+
progressIndicatorDelay: progressIndicatorDelay ?? this.progressIndicatorDelay,
469461
pauseOnBackgroundTap: pauseOnBackgroundTap ?? this.pauseOnBackgroundTap,
462+
swipeToExitFullscreen: swipeToExitFullscreen ?? this.swipeToExitFullscreen,
463+
swipeThreshold: swipeThreshold ?? this.swipeThreshold,
470464
);
471465
}
472466

@@ -493,8 +487,7 @@ class ChewieController extends ChangeNotifier {
493487
final Future<void> Function(
494488
BuildContext context,
495489
List<OptionItem> chewieOptions,
496-
)?
497-
optionsBuilder;
490+
)? optionsBuilder;
498491

499492
/// Add your own additional options on top of chewie options
500493
final List<OptionItem> Function(BuildContext context)? additionalOptions;
@@ -554,8 +547,7 @@ class ChewieController extends ChangeNotifier {
554547

555548
/// When the video playback runs into an error, you can build a custom
556549
/// error message.
557-
final Widget Function(BuildContext context, String errorMessage)?
558-
errorBuilder;
550+
final Widget Function(BuildContext context, String errorMessage)? errorBuilder;
559551

560552
/// When the video is buffering, you can build a custom widget.
561553
final WidgetBuilder? bufferingBuilder;
@@ -639,9 +631,15 @@ class ChewieController extends ChangeNotifier {
639631
/// Defines if the player should pause when the background is tapped
640632
final bool pauseOnBackgroundTap;
641633

634+
/// Defines if the player allows swipe to exit fullscreen
635+
final bool swipeToExitFullscreen;
636+
637+
/// Defines the minimum velocity threshold for swipe to exit fullscreen gesture
638+
/// The velocity is measured in pixels per second
639+
final double swipeThreshold;
640+
642641
static ChewieController of(BuildContext context) {
643-
final chewieControllerProvider = context
644-
.dependOnInheritedWidgetOfExactType<ChewieControllerProvider>()!;
642+
final chewieControllerProvider = context.dependOnInheritedWidgetOfExactType<ChewieControllerProvider>()!;
645643

646644
return chewieControllerProvider.controller;
647645
}
@@ -655,8 +653,7 @@ class ChewieController extends ChangeNotifier {
655653
Future<dynamic> _initialize() async {
656654
await videoPlayerController.setLooping(looping);
657655

658-
if ((autoInitialize || autoPlay) &&
659-
!videoPlayerController.value.isInitialized) {
656+
if ((autoInitialize || autoPlay) && !videoPlayerController.value.isInitialized) {
660657
await videoPlayerController.initialize();
661658
}
662659

@@ -739,6 +736,5 @@ class ChewieControllerProvider extends InheritedWidget {
739736
final ChewieController controller;
740737

741738
@override
742-
bool updateShouldNotify(ChewieControllerProvider oldWidget) =>
743-
controller != oldWidget.controller;
739+
bool updateShouldNotify(ChewieControllerProvider oldWidget) => controller != oldWidget.controller;
744740
}

0 commit comments

Comments
 (0)