diff --git a/example/lib/app/app.dart b/example/lib/app/app.dart index 4718733a8..6d7ed53d2 100644 --- a/example/lib/app/app.dart +++ b/example/lib/app/app.dart @@ -23,6 +23,7 @@ class _ChewieDemoState extends State { late VideoPlayerController _videoPlayerController1; late VideoPlayerController _videoPlayerController2; ChewieController? _chewieController; + int? bufferDelay; @override void initState() { @@ -111,6 +112,7 @@ class _ChewieDemoState extends State { videoPlayerController: _videoPlayerController1, autoPlay: true, looping: true, + progressIndicatorDelayMS: bufferDelay, additionalOptions: (context) { return [ @@ -304,9 +306,86 @@ class _ChewieDemoState extends State { ), ], ), + ListTile( + title: const Text("Delay"), + subtitle: Column( + children: [ + DelaySlider( + delay: _chewieController?.progressIndicatorDelayMS, + onSave: (delay) async { + if (delay != null) { + if (delay == 0) { + bufferDelay = null; + } else { + bufferDelay = delay; + } + + await initializePlayer(); + } + }, + ), + Text( + _chewieController?.progressIndicatorDelayMS != null + ? "Progress indicator delay ${_chewieController!.progressIndicatorDelayMS.toString()} MS" + : "Set me", + ), + ], + ), + ) ], ), ), ); } } + +class DelaySlider extends StatefulWidget { + const DelaySlider({Key? key, required this.delay, required this.onSave}) + : super(key: key); + + final int? delay; + final void Function(int?) onSave; + @override + State createState() => _DelaySliderState(); +} + +class _DelaySliderState extends State { + int? delay; + bool saved = false; + + @override + void initState() { + super.initState(); + delay = widget.delay; + } + + @override + Widget build(BuildContext context) { + const int max = 1000; + return ListTile( + title: Text( + "Progress indicator delay ${delay != null ? "${delay.toString()} MS" : ""}", + ), + subtitle: Slider( + value: delay != null ? (delay! / max) : 0, + onChanged: (value) async { + delay = (value * max).toInt(); + setState(() { + saved = false; + }); + }, + ), + trailing: IconButton( + icon: const Icon(Icons.save), + onPressed: saved + ? null + : () { + widget.onSave(delay); + setState(() { + saved = true; + }); + }, + ), + ); + } +} diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart index bffb4d2e9..da1d48c3a 100644 --- a/lib/src/chewie_player.dart +++ b/lib/src/chewie_player.dart @@ -280,6 +280,7 @@ class ChewieController extends ChangeNotifier { this.systemOverlaysAfterFullScreen = SystemUiOverlay.values, this.deviceOrientationsAfterFullScreen = DeviceOrientation.values, this.routePageBuilder, + this.progressIndicatorDelayMS, }) : assert( playbackSpeeds.every((speed) => speed > 0), 'The playbackSpeeds values must all be greater than 0', @@ -322,6 +323,7 @@ class ChewieController extends ChangeNotifier { List? deviceOrientationsOnEnterFullScreen, List? systemOverlaysAfterFullScreen, List? deviceOrientationsAfterFullScreen, + int? bufferingProgressIndicatorDisplayDelayMS, Widget Function( BuildContext, Animation, @@ -331,50 +333,51 @@ class ChewieController extends ChangeNotifier { routePageBuilder, }) { return ChewieController( - videoPlayerController: - videoPlayerController ?? this.videoPlayerController, - optionsTranslation: optionsTranslation ?? this.optionsTranslation, - aspectRatio: aspectRatio ?? this.aspectRatio, - autoInitialize: autoInitialize ?? this.autoInitialize, - autoPlay: autoPlay ?? this.autoPlay, - startAt: startAt ?? this.startAt, - looping: looping ?? this.looping, - fullScreenByDefault: fullScreenByDefault ?? this.fullScreenByDefault, - cupertinoProgressColors: - cupertinoProgressColors ?? this.cupertinoProgressColors, - materialProgressColors: - materialProgressColors ?? this.materialProgressColors, - placeholder: placeholder ?? this.placeholder, - overlay: overlay ?? this.overlay, - showControlsOnInitialize: - showControlsOnInitialize ?? this.showControlsOnInitialize, - showOptions: showOptions ?? this.showOptions, - optionsBuilder: optionsBuilder ?? this.optionsBuilder, - additionalOptions: additionalOptions ?? this.additionalOptions, - showControls: showControls ?? this.showControls, - subtitle: subtitle ?? this.subtitle, - subtitleBuilder: subtitleBuilder ?? this.subtitleBuilder, - customControls: customControls ?? this.customControls, - errorBuilder: errorBuilder ?? this.errorBuilder, - allowedScreenSleep: allowedScreenSleep ?? this.allowedScreenSleep, - isLive: isLive ?? this.isLive, - allowFullScreen: allowFullScreen ?? this.allowFullScreen, - allowMuting: allowMuting ?? this.allowMuting, - allowPlaybackSpeedChanging: - allowPlaybackSpeedChanging ?? this.allowPlaybackSpeedChanging, - useRootNavigator: useRootNavigator ?? this.useRootNavigator, - playbackSpeeds: playbackSpeeds ?? this.playbackSpeeds, - systemOverlaysOnEnterFullScreen: systemOverlaysOnEnterFullScreen ?? - this.systemOverlaysOnEnterFullScreen, - deviceOrientationsOnEnterFullScreen: - deviceOrientationsOnEnterFullScreen ?? - this.deviceOrientationsOnEnterFullScreen, - systemOverlaysAfterFullScreen: - systemOverlaysAfterFullScreen ?? this.systemOverlaysAfterFullScreen, - deviceOrientationsAfterFullScreen: deviceOrientationsAfterFullScreen ?? - this.deviceOrientationsAfterFullScreen, - routePageBuilder: routePageBuilder ?? this.routePageBuilder, - ); + videoPlayerController: + videoPlayerController ?? this.videoPlayerController, + optionsTranslation: optionsTranslation ?? this.optionsTranslation, + aspectRatio: aspectRatio ?? this.aspectRatio, + autoInitialize: autoInitialize ?? this.autoInitialize, + autoPlay: autoPlay ?? this.autoPlay, + startAt: startAt ?? this.startAt, + looping: looping ?? this.looping, + fullScreenByDefault: fullScreenByDefault ?? this.fullScreenByDefault, + cupertinoProgressColors: + cupertinoProgressColors ?? this.cupertinoProgressColors, + materialProgressColors: + materialProgressColors ?? this.materialProgressColors, + placeholder: placeholder ?? this.placeholder, + overlay: overlay ?? this.overlay, + showControlsOnInitialize: + showControlsOnInitialize ?? this.showControlsOnInitialize, + showOptions: showOptions ?? this.showOptions, + optionsBuilder: optionsBuilder ?? this.optionsBuilder, + additionalOptions: additionalOptions ?? this.additionalOptions, + showControls: showControls ?? this.showControls, + subtitle: subtitle ?? this.subtitle, + subtitleBuilder: subtitleBuilder ?? this.subtitleBuilder, + customControls: customControls ?? this.customControls, + errorBuilder: errorBuilder ?? this.errorBuilder, + allowedScreenSleep: allowedScreenSleep ?? this.allowedScreenSleep, + isLive: isLive ?? this.isLive, + allowFullScreen: allowFullScreen ?? this.allowFullScreen, + allowMuting: allowMuting ?? this.allowMuting, + allowPlaybackSpeedChanging: + allowPlaybackSpeedChanging ?? this.allowPlaybackSpeedChanging, + useRootNavigator: useRootNavigator ?? this.useRootNavigator, + playbackSpeeds: playbackSpeeds ?? this.playbackSpeeds, + systemOverlaysOnEnterFullScreen: systemOverlaysOnEnterFullScreen ?? + this.systemOverlaysOnEnterFullScreen, + deviceOrientationsOnEnterFullScreen: + deviceOrientationsOnEnterFullScreen ?? + this.deviceOrientationsOnEnterFullScreen, + systemOverlaysAfterFullScreen: + systemOverlaysAfterFullScreen ?? this.systemOverlaysAfterFullScreen, + deviceOrientationsAfterFullScreen: deviceOrientationsAfterFullScreen ?? + this.deviceOrientationsAfterFullScreen, + routePageBuilder: routePageBuilder ?? this.routePageBuilder, + progressIndicatorDelayMS: bufferingProgressIndicatorDisplayDelayMS ?? + this.progressIndicatorDelayMS); } /// If false, the options button in MaterialUI and MaterialDesktopUI @@ -505,6 +508,9 @@ class ChewieController extends ChangeNotifier { /// Defines a custom RoutePageBuilder for the fullscreen final ChewieRoutePageBuilder? routePageBuilder; + /// [Android] Defines a delay in milliseconds between entering buffering state and displaying the loading spinner. Set null (default) to disable it. + final int? progressIndicatorDelayMS; + static ChewieController of(BuildContext context) { final chewieControllerProvider = context.dependOnInheritedWidgetOfExactType()!; diff --git a/lib/src/material/material_controls.dart b/lib/src/material/material_controls.dart index b286d314f..78016eff6 100644 --- a/lib/src/material/material_controls.dart +++ b/lib/src/material/material_controls.dart @@ -560,12 +560,22 @@ class _MaterialControlsState extends State void _updateState() { if (!mounted) return; - if (controller.value.isBuffering) { - timerInstance ??= Timer(const Duration(milliseconds: 200), handleTimeout); + // display the progress bar indicator only after the buffering delay if it has been set + if (chewieController.progressIndicatorDelayMS != null) { + if (controller.value.isBuffering) { + timerInstance ??= Timer( + Duration( + milliseconds: chewieController.progressIndicatorDelayMS!, + ), + handleTimeout, + ); + } else { + timerInstance?.cancel(); + timerInstance = null; + displayLoading = false; + } } else { - timerInstance?.cancel(); - timerInstance = null; - displayLoading = false; + displayLoading = controller.value.isBuffering; } setState(() {