chewie_player.dart 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import 'dart:async';
  2. import 'package:chewie/src/chewie_progress_colors.dart';
  3. import 'package:chewie/src/player_with_controls.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:flutter/services.dart';
  6. import 'package:flutter/widgets.dart';
  7. import 'package:video_player/video_player.dart';
  8. /// A Video Player with Material and Cupertino skins.
  9. ///
  10. /// `video_player` is pretty low level. Chewie wraps it in a friendly skin to
  11. /// make it easy to use!
  12. class Chewie extends StatefulWidget {
  13. /// The Controller for the Video you want to play
  14. final VideoPlayerController controller;
  15. /// Initialize the Video on Startup. This will prep the video for playback.
  16. final bool autoInitialize;
  17. /// Play the video as soon as it's displayed
  18. final bool autoPlay;
  19. /// Start video at a certain position
  20. final Duration startAt;
  21. /// Whether or not the video should loop
  22. final bool looping;
  23. /// Whether or not to show the controls
  24. final bool showControls;
  25. /// The Aspect Ratio of the Video. Important to get the correct size of the
  26. /// video!
  27. ///
  28. /// Will fallback to fitting within the space allowed.
  29. final double aspectRatio;
  30. /// The colors to use for controls on iOS. By default, the iOS player uses
  31. /// colors sampled from the original iOS 11 designs.
  32. final ChewieProgressColors cupertinoProgressColors;
  33. /// The colors to use for the Material Progress Bar. By default, the Material
  34. /// player uses the colors from your Theme.
  35. final ChewieProgressColors materialProgressColors;
  36. /// The placeholder is displayed underneath the Video before it is initialized
  37. /// or played.
  38. final Widget placeholder;
  39. Chewie(
  40. this.controller, {
  41. Key key,
  42. this.aspectRatio,
  43. this.autoInitialize = false,
  44. this.autoPlay = false,
  45. this.startAt,
  46. this.looping = false,
  47. this.cupertinoProgressColors,
  48. this.materialProgressColors,
  49. this.placeholder,
  50. this.showControls = true,
  51. }) : assert(controller != null,
  52. 'You must provide a controller to play a video'),
  53. super(key: key);
  54. @override
  55. State<StatefulWidget> createState() {
  56. return new _ChewiePlayerState();
  57. }
  58. }
  59. class _ChewiePlayerState extends State<Chewie> {
  60. VideoPlayerController _controller;
  61. @override
  62. Widget build(BuildContext context) {
  63. return new PlayerWithControls(
  64. controller: _controller,
  65. onExpandCollapse: () => _pushFullScreenWidget(context),
  66. aspectRatio: widget.aspectRatio ?? _calculateAspectRatio(context),
  67. cupertinoProgressColors: widget.cupertinoProgressColors,
  68. materialProgressColors: widget.materialProgressColors,
  69. placeholder: widget.placeholder,
  70. autoPlay: widget.autoPlay,
  71. showControls: widget.showControls,
  72. );
  73. }
  74. @override
  75. void initState() {
  76. super.initState();
  77. _controller = widget.controller;
  78. _initialize();
  79. }
  80. Widget _buildFullScreenVideo(
  81. BuildContext context, Animation<double> animation) {
  82. return new Scaffold(
  83. resizeToAvoidBottomPadding: false,
  84. body: new Container(
  85. alignment: Alignment.center,
  86. color: Colors.black,
  87. child: new PlayerWithControls(
  88. controller: _controller,
  89. onExpandCollapse: () =>
  90. new Future<dynamic>.value(Navigator.of(context).pop()),
  91. aspectRatio: widget.aspectRatio ?? _calculateAspectRatio(context),
  92. fullScreen: true,
  93. cupertinoProgressColors: widget.cupertinoProgressColors,
  94. materialProgressColors: widget.materialProgressColors,
  95. ),
  96. ),
  97. );
  98. }
  99. Widget _fullScreenRoutePageBuilder(
  100. BuildContext context,
  101. Animation<double> animation,
  102. Animation<double> secondaryAnimation,
  103. ) {
  104. return new AnimatedBuilder(
  105. animation: animation,
  106. builder: (BuildContext context, Widget child) {
  107. return _buildFullScreenVideo(context, animation);
  108. },
  109. );
  110. }
  111. Future _initialize() async {
  112. await _controller.setLooping(widget.looping);
  113. if (widget.autoInitialize || widget.autoPlay) {
  114. await _controller.initialize();
  115. }
  116. if (widget.autoPlay) {
  117. await _controller.play();
  118. }
  119. if (widget.startAt != null) {
  120. await _controller.seekTo(widget.startAt);
  121. }
  122. }
  123. @override
  124. void didUpdateWidget(Chewie oldWidget) {
  125. super.didUpdateWidget(oldWidget);
  126. if (widget.controller.dataSource != _controller.dataSource) {
  127. _controller.dispose();
  128. _controller = widget.controller;
  129. _initialize();
  130. }
  131. }
  132. Future<dynamic> _pushFullScreenWidget(BuildContext context) async {
  133. final isAndroid = Theme.of(context).platform == TargetPlatform.android;
  134. final TransitionRoute<Null> route = new PageRouteBuilder<Null>(
  135. settings: new RouteSettings(isInitialRoute: false),
  136. pageBuilder: _fullScreenRoutePageBuilder,
  137. );
  138. SystemChrome.setEnabledSystemUIOverlays([]);
  139. if (isAndroid) {
  140. SystemChrome.setPreferredOrientations([
  141. DeviceOrientation.landscapeLeft,
  142. DeviceOrientation.landscapeRight,
  143. ]);
  144. }
  145. await Navigator.of(context).push(route);
  146. SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
  147. SystemChrome.setPreferredOrientations([
  148. DeviceOrientation.portraitUp,
  149. DeviceOrientation.portraitDown,
  150. DeviceOrientation.landscapeLeft,
  151. DeviceOrientation.landscapeRight,
  152. ]);
  153. }
  154. double _calculateAspectRatio(BuildContext context) {
  155. final size = MediaQuery.of(context).size;
  156. final width = size.width;
  157. final height = size.height;
  158. return width > height ? width / height : height / width;
  159. }
  160. }