LocalVideoPlayer.dart 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'package:flutter/material.dart';
  4. import 'package:video_player/video_player.dart';
  5. import 'package:flutter/services.dart';
  6. import 'package:screen/screen.dart';
  7. class LocalVideoPlayer extends StatefulWidget {
  8. final String source;
  9. bool isFullScreen;
  10. bool isNet;
  11. LocalVideoPlayer(this.source,
  12. {this.isFullScreen = false, this.isNet = false});
  13. @override
  14. _LocalVideoPlayerState createState() => _LocalVideoPlayerState();
  15. }
  16. class _LocalVideoPlayerState extends State<LocalVideoPlayer> {
  17. VideoPlayerController controller;
  18. VoidCallback listener;
  19. bool hideBottom = true;
  20. @override
  21. void initState() {
  22. super.initState();
  23. listener = () {
  24. if (!mounted) {
  25. return;
  26. }
  27. setState(() {});
  28. };
  29. if (widget.isNet) {
  30. print(widget.source);
  31. controller = VideoPlayerController.network(widget.source);
  32. } else {
  33. File _sourceFile = File('file://${widget.source}');
  34. controller = VideoPlayerController.file(_sourceFile);
  35. }
  36. controller.initialize();
  37. controller.setLooping(true);
  38. controller.addListener(listener);
  39. controller.play();
  40. Screen.keepOn(true);
  41. if (widget.isFullScreen) {
  42. SystemChrome.setEnabledSystemUIOverlays([]);
  43. SystemChrome.setPreferredOrientations([
  44. DeviceOrientation.landscapeLeft,
  45. DeviceOrientation.landscapeRight,
  46. ]);
  47. }
  48. }
  49. @override
  50. void dispose() {
  51. controller.dispose();
  52. Screen.keepOn(false);
  53. if (widget.isFullScreen) {
  54. SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
  55. SystemChrome.setPreferredOrientations([
  56. DeviceOrientation.portraitUp,
  57. DeviceOrientation.portraitDown,
  58. DeviceOrientation.landscapeLeft,
  59. DeviceOrientation.landscapeRight,
  60. ]);
  61. }
  62. super.dispose();
  63. }
  64. @override
  65. Widget build(BuildContext context) {
  66. return Scaffold(
  67. body: PlayView(
  68. controller,
  69. allowFullScreen: !widget.isFullScreen,
  70. ),
  71. );
  72. }
  73. }
  74. class PlayView extends StatefulWidget {
  75. VideoPlayerController controller;
  76. bool allowFullScreen;
  77. PlayView(this.controller, {this.allowFullScreen = true});
  78. @override
  79. _PlayViewState createState() => _PlayViewState();
  80. }
  81. class _PlayViewState extends State<PlayView> {
  82. VideoPlayerController get controller => widget.controller;
  83. bool hideBottom = true;
  84. void onClickPlay() {
  85. if (!controller.value.initialized) {
  86. return;
  87. }
  88. setState(() {
  89. hideBottom = false;
  90. });
  91. if (controller.value.isPlaying) {
  92. controller.pause();
  93. } else {
  94. Future.delayed(const Duration(seconds: 3), () {
  95. if (!mounted) {
  96. return;
  97. }
  98. if (!controller.value.initialized) {
  99. return;
  100. }
  101. if (controller.value.isPlaying && !hideBottom) {
  102. setState(() {
  103. hideBottom = true;
  104. });
  105. }
  106. });
  107. controller.play();
  108. }
  109. }
  110. void onClickFullScreen() {
  111. if (MediaQuery.of(context).orientation == Orientation.portrait) {
  112. // current portrait , enter fullscreen
  113. SystemChrome.setEnabledSystemUIOverlays([]);
  114. SystemChrome.setPreferredOrientations([
  115. DeviceOrientation.landscapeLeft,
  116. DeviceOrientation.landscapeRight,
  117. ]);
  118. Navigator.of(context)
  119. .push(PageRouteBuilder(
  120. settings: RouteSettings(isInitialRoute: false),
  121. pageBuilder: (
  122. BuildContext context,
  123. Animation<double> animation,
  124. Animation<double> secondaryAnimation,
  125. ) {
  126. return AnimatedBuilder(
  127. animation: animation,
  128. builder: (BuildContext context, Widget child) {
  129. return Scaffold(
  130. resizeToAvoidBottomPadding: false,
  131. body: PlayView(controller),
  132. );
  133. },
  134. );
  135. },
  136. ))
  137. .then((value) {
  138. // exit fullscreen
  139. SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
  140. SystemChrome.setPreferredOrientations([
  141. DeviceOrientation.portraitUp,
  142. DeviceOrientation.portraitDown,
  143. DeviceOrientation.landscapeLeft,
  144. DeviceOrientation.landscapeRight,
  145. ]);
  146. });
  147. }
  148. }
  149. void onClickExitFullScreen() {
  150. if (MediaQuery.of(context).orientation == Orientation.landscape) {
  151. // current landscape , exit fullscreen
  152. Navigator.of(context).pop();
  153. }
  154. }
  155. @override
  156. Widget build(BuildContext context) {
  157. Color primaryColor = Theme.of(context).primaryColor;
  158. if (controller.value.initialized) {
  159. final Size size = controller.value.size;
  160. return GestureDetector(
  161. child: Container(
  162. color: Colors.black,
  163. child: Stack(
  164. children: <Widget>[
  165. Center(
  166. child: AspectRatio(
  167. aspectRatio: size.width / size.height,
  168. child: VideoPlayer(controller),
  169. )),
  170. Align(
  171. alignment: Alignment.bottomCenter,
  172. child: hideBottom
  173. ? Container()
  174. : Opacity(
  175. opacity: 0.8,
  176. child: Container(
  177. height: 30.0,
  178. color: Colors.grey,
  179. child: Row(
  180. mainAxisSize: MainAxisSize.max,
  181. children: <Widget>[
  182. GestureDetector(
  183. child: Container(
  184. child: controller.value.isPlaying
  185. ? Icon(
  186. Icons.pause,
  187. color: primaryColor,
  188. )
  189. : Icon(
  190. Icons.play_arrow,
  191. color: primaryColor,
  192. ),
  193. ),
  194. onTap: onClickPlay,
  195. ),
  196. Container(
  197. padding: EdgeInsets.symmetric(
  198. horizontal: 5.0),
  199. child: Center(
  200. child: Text(
  201. '${controller.value.position.toString().split('.')[0]}',
  202. style:
  203. TextStyle(color: Colors.white),
  204. ),
  205. )),
  206. Expanded(
  207. child: VideoProgressIndicator(
  208. controller,
  209. allowScrubbing: true,
  210. padding: EdgeInsets.symmetric(
  211. horizontal: 1.0, vertical: 1.0),
  212. colors: VideoProgressColors(
  213. playedColor: primaryColor),
  214. )),
  215. Container(
  216. padding: EdgeInsets.symmetric(
  217. horizontal: 5.0),
  218. child: Center(
  219. child: Text(
  220. '${controller.value.duration.toString().split('.')[0]}',
  221. style:
  222. TextStyle(color: Colors.white),
  223. ),
  224. )),
  225. Container(
  226. child: widget.allowFullScreen
  227. ? Container(
  228. child: MediaQuery.of(context)
  229. .orientation ==
  230. Orientation.portrait
  231. ? GestureDetector(
  232. child: Icon(
  233. Icons.fullscreen,
  234. color: primaryColor,
  235. ),
  236. onTap: onClickFullScreen,
  237. )
  238. : GestureDetector(
  239. child: Icon(
  240. Icons.fullscreen_exit,
  241. color: primaryColor,
  242. ),
  243. onTap:
  244. onClickExitFullScreen,
  245. ),
  246. )
  247. : Container(),
  248. )
  249. ],
  250. )),
  251. )),
  252. Align(
  253. alignment: Alignment.center,
  254. child: controller.value.isPlaying
  255. ? Container()
  256. : Icon(
  257. Icons.play_circle_filled,
  258. color: primaryColor,
  259. size: 48.0,
  260. ),
  261. )
  262. ],
  263. )),
  264. onTap: onClickPlay,
  265. );
  266. } else if (controller.value.hasError && !controller.value.isPlaying) {
  267. return Container(
  268. color: Colors.black,
  269. child: Center(
  270. child: RaisedButton(
  271. onPressed: () {
  272. controller.initialize();
  273. controller.setLooping(true);
  274. controller.play();
  275. },
  276. shape: RoundedRectangleBorder(
  277. borderRadius: BorderRadius.circular(30.0)),
  278. child: Text('play error, try again!'),
  279. ),
  280. ),
  281. );
  282. } else {
  283. return Container(
  284. color: Colors.black,
  285. child: Center(
  286. child: CircularProgressIndicator(),
  287. ),
  288. );
  289. }
  290. }
  291. }