|
|
@@ -1,112 +1,63 @@
|
|
|
import 'dart:async';
|
|
|
|
|
|
-import 'package:chewie/src/chewie_progress_colors.dart';
|
|
|
+import 'package:chewie/src/chewie_controller.dart';
|
|
|
import 'package:chewie/src/player_with_controls.dart';
|
|
|
import 'package:flutter/material.dart';
|
|
|
import 'package:flutter/services.dart';
|
|
|
import 'package:flutter/widgets.dart';
|
|
|
import 'package:screen/screen.dart';
|
|
|
-import 'package:video_player/video_player.dart';
|
|
|
|
|
|
/// A Video Player with Material and Cupertino skins.
|
|
|
///
|
|
|
/// `video_player` is pretty low level. Chewie wraps it in a friendly skin to
|
|
|
/// make it easy to use!
|
|
|
class Chewie extends StatefulWidget {
|
|
|
- /// The Controller for the Video you want to play
|
|
|
- final VideoPlayerController controller;
|
|
|
-
|
|
|
- /// Initialize the Video on Startup. This will prep the video for playback.
|
|
|
- final bool autoInitialize;
|
|
|
-
|
|
|
- /// Play the video as soon as it's displayed
|
|
|
- final bool autoPlay;
|
|
|
-
|
|
|
- /// Start video at a certain position
|
|
|
- final Duration startAt;
|
|
|
-
|
|
|
- /// Whether or not the video should loop
|
|
|
- final bool looping;
|
|
|
-
|
|
|
- /// Whether or not to show the controls
|
|
|
- final bool showControls;
|
|
|
-
|
|
|
- /// The Aspect Ratio of the Video. Important to get the correct size of the
|
|
|
- /// video!
|
|
|
- ///
|
|
|
- /// Will fallback to fitting within the space allowed.
|
|
|
- final double aspectRatio;
|
|
|
-
|
|
|
- /// The colors to use for controls on iOS. By default, the iOS player uses
|
|
|
- /// colors sampled from the original iOS 11 designs.
|
|
|
- final ChewieProgressColors cupertinoProgressColors;
|
|
|
-
|
|
|
- /// The colors to use for the Material Progress Bar. By default, the Material
|
|
|
- /// player uses the colors from your Theme.
|
|
|
- final ChewieProgressColors materialProgressColors;
|
|
|
-
|
|
|
- /// The placeholder is displayed underneath the Video before it is initialized
|
|
|
- /// or played.
|
|
|
- final Widget placeholder;
|
|
|
-
|
|
|
- /// Defines if the player will start in fullscreen when play is pressed
|
|
|
- final bool fullScreenByDefault;
|
|
|
-
|
|
|
- /// Defines if the player will sleep in fullscreen or not
|
|
|
- final bool allowedScreenSleep;
|
|
|
-
|
|
|
- /// Defines if the controls should be for live stream video
|
|
|
- final bool isLive;
|
|
|
-
|
|
|
- Chewie(
|
|
|
- this.controller, {
|
|
|
+ Chewie({
|
|
|
Key key,
|
|
|
- this.aspectRatio,
|
|
|
- this.autoInitialize = false,
|
|
|
- this.autoPlay = false,
|
|
|
- this.startAt,
|
|
|
- this.looping = false,
|
|
|
- this.fullScreenByDefault = false,
|
|
|
- this.cupertinoProgressColors,
|
|
|
- this.materialProgressColors,
|
|
|
- this.placeholder,
|
|
|
- this.showControls = true,
|
|
|
- this.allowedScreenSleep = true,
|
|
|
- this.isLive = false,
|
|
|
- }) : assert(controller != null,
|
|
|
- 'You must provide a controller to play a video'),
|
|
|
+ this.controller,
|
|
|
+ }) : assert(controller != null, 'You must provide a chewie controller'),
|
|
|
super(key: key);
|
|
|
|
|
|
+ /// The [ChewieController]
|
|
|
+ final ChewieController controller;
|
|
|
+
|
|
|
@override
|
|
|
- State<StatefulWidget> createState() {
|
|
|
- return _ChewiePlayerState();
|
|
|
+ ChewieState createState() {
|
|
|
+ return ChewieState();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-class _ChewiePlayerState extends State<Chewie> {
|
|
|
- VideoPlayerController _controller;
|
|
|
+class ChewieState extends State<Chewie> {
|
|
|
bool _isFullScreen = false;
|
|
|
|
|
|
@override
|
|
|
- Widget build(BuildContext context) {
|
|
|
- return PlayerWithControls(
|
|
|
- controller: _controller,
|
|
|
- onExpandCollapse: () => _pushFullScreenWidget(context),
|
|
|
- aspectRatio: widget.aspectRatio ?? _calculateAspectRatio(context),
|
|
|
- cupertinoProgressColors: widget.cupertinoProgressColors,
|
|
|
- materialProgressColors: widget.materialProgressColors,
|
|
|
- placeholder: widget.placeholder,
|
|
|
- autoPlay: widget.autoPlay,
|
|
|
- showControls: widget.showControls,
|
|
|
- isLive: widget.isLive,
|
|
|
- );
|
|
|
+ void initState() {
|
|
|
+ super.initState();
|
|
|
+ widget.controller.addListener(listener);
|
|
|
}
|
|
|
|
|
|
@override
|
|
|
- void initState() {
|
|
|
- super.initState();
|
|
|
- _controller = widget.controller;
|
|
|
- _initialize();
|
|
|
+ void dispose() {
|
|
|
+ widget.controller.removeListener(listener);
|
|
|
+ super.dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ void listener() async {
|
|
|
+ if (widget.controller.value.isFullScreen && !_isFullScreen) {
|
|
|
+ _isFullScreen = true;
|
|
|
+ await _pushFullScreenWidget(context);
|
|
|
+ } else if (_isFullScreen) {
|
|
|
+ Navigator.of(context).pop();
|
|
|
+ _isFullScreen = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return ChewieControllerProvider(
|
|
|
+ controller: widget.controller,
|
|
|
+ child: PlayerWithControls(),
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
Widget _buildFullScreenVideo(
|
|
|
@@ -116,15 +67,9 @@ class _ChewiePlayerState extends State<Chewie> {
|
|
|
body: Container(
|
|
|
alignment: Alignment.center,
|
|
|
color: Colors.black,
|
|
|
- child: PlayerWithControls(
|
|
|
- controller: _controller,
|
|
|
- onExpandCollapse: () =>
|
|
|
- Future<dynamic>.value(Navigator.of(context).pop()),
|
|
|
- aspectRatio: widget.aspectRatio ?? _calculateAspectRatio(context),
|
|
|
- fullScreen: true,
|
|
|
- isLive: widget.isLive,
|
|
|
- cupertinoProgressColors: widget.cupertinoProgressColors,
|
|
|
- materialProgressColors: widget.materialProgressColors,
|
|
|
+ child: ChewieControllerProvider(
|
|
|
+ controller: widget.controller,
|
|
|
+ child: PlayerWithControls(),
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
@@ -143,48 +88,6 @@ class _ChewiePlayerState extends State<Chewie> {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- Future _initialize() async {
|
|
|
- await _controller.setLooping(widget.looping);
|
|
|
-
|
|
|
- if (widget.autoInitialize || widget.autoPlay) {
|
|
|
- await _controller.initialize();
|
|
|
- }
|
|
|
-
|
|
|
- if (widget.autoPlay) {
|
|
|
- if (widget.fullScreenByDefault) {
|
|
|
- _isFullScreen = true;
|
|
|
- await _pushFullScreenWidget(context);
|
|
|
- }
|
|
|
-
|
|
|
- await _controller.play();
|
|
|
- }
|
|
|
-
|
|
|
- if (widget.startAt != null) {
|
|
|
- await _controller.seekTo(widget.startAt);
|
|
|
- }
|
|
|
-
|
|
|
- if (widget.fullScreenByDefault) {
|
|
|
- widget.controller.addListener(() async {
|
|
|
- if (await widget.controller.value.isPlaying && !_isFullScreen) {
|
|
|
- _isFullScreen = true;
|
|
|
- await _pushFullScreenWidget(context);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @override
|
|
|
- void didUpdateWidget(Chewie oldWidget) {
|
|
|
- super.didUpdateWidget(oldWidget);
|
|
|
-
|
|
|
- if (widget.controller.dataSource != _controller.dataSource) {
|
|
|
- _controller.dispose();
|
|
|
- _controller = widget.controller;
|
|
|
- _isFullScreen = false;
|
|
|
- _initialize();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
Future<dynamic> _pushFullScreenWidget(BuildContext context) async {
|
|
|
final isAndroid = Theme.of(context).platform == TargetPlatform.android;
|
|
|
final TransitionRoute<Null> route = PageRouteBuilder<Null>(
|
|
|
@@ -200,7 +103,7 @@ class _ChewiePlayerState extends State<Chewie> {
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
- if (!widget.allowedScreenSleep) {
|
|
|
+ if (!widget.controller.allowedScreenSleep) {
|
|
|
Screen.keepOn(true);
|
|
|
}
|
|
|
|
|
|
@@ -219,12 +122,4 @@ class _ChewiePlayerState extends State<Chewie> {
|
|
|
DeviceOrientation.landscapeRight,
|
|
|
]);
|
|
|
}
|
|
|
-
|
|
|
- double _calculateAspectRatio(BuildContext context) {
|
|
|
- final size = MediaQuery.of(context).size;
|
|
|
- final width = size.width;
|
|
|
- final height = size.height;
|
|
|
-
|
|
|
- return width > height ? width / height : height / width;
|
|
|
- }
|
|
|
}
|