YSFileView.dart 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. import 'dart:io';
  2. import 'package:dio/dio.dart';
  3. import 'package:file_picker/file_picker.dart';
  4. import 'package:file_preview/file_preview.dart';
  5. import 'package:flutter/cupertino.dart';
  6. import 'package:flutter/material.dart';
  7. import 'package:flutter/services.dart';
  8. import 'package:path_provider/path_provider.dart';
  9. import 'package:video_player/video_player.dart';
  10. import 'package:video_thumbnail/video_thumbnail.dart';
  11. import '../base/YSBase.dart';
  12. import 'YSAlertView.dart';
  13. import 'YSNetWork.dart';
  14. import 'YSTools.dart';
  15. String fileUrl = 'https://cdn.datangyun.cc/';
  16. class YSFileView extends StatelessWidget {
  17. final List fileArray;
  18. const YSFileView({Key? key, required this.fileArray}) : super(key: key);
  19. @override
  20. Widget build(BuildContext context) {
  21. return LayoutBuilder(builder: (context,conSize){
  22. return GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  23. crossAxisCount: 4,
  24. childAspectRatio: 54/35,
  25. crossAxisSpacing: hsp(15),
  26. mainAxisSpacing: hsp(15)
  27. ), itemBuilder: (context,index){
  28. Map item = fileArray[index];
  29. return item['type']==1?YSImageView(
  30. url: item['url'],
  31. ):YSVideoView(
  32. url: item['url']
  33. );
  34. },shrinkWrap: true,padding: const EdgeInsets.all(0),physics: const NeverScrollableScrollPhysics(),itemCount: fileArray.length,);
  35. });
  36. }
  37. }
  38. class YSUploadFileView2 extends StatefulWidget {
  39. final List fileArray;
  40. const YSUploadFileView2({Key? key, required this.fileArray}) : super(key: key);
  41. @override
  42. YSUploadFileView2State createState() => YSUploadFileView2State();
  43. }
  44. class YSUploadFileView2State extends State<YSUploadFileView2> {
  45. @override
  46. void initState() {
  47. super.initState();
  48. }
  49. @override
  50. Widget build(BuildContext context) {
  51. return LayoutBuilder(builder: (context,conSize){
  52. return GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  53. crossAxisCount: 4,
  54. childAspectRatio: 54/35,
  55. crossAxisSpacing: hsp(15),
  56. mainAxisSpacing: hsp(15)
  57. ), itemBuilder: (context,index){
  58. return GestureDetector(
  59. onTap: () async{
  60. // LogUtil.d('obj');
  61. // return;
  62. if(index==0){//&&widget.fileArray.isEmpty
  63. if(widget.fileArray.length==4){
  64. ysFlutterToast('最多添加4个文件');
  65. return;
  66. }
  67. FocusScope.of(context).unfocus();
  68. bool isAgree = await permissionHandler('file');
  69. if(isAgree==false)return;
  70. List<String> allowedExtensions = ['jpg','jpeg','png','mp4'];
  71. bool isMp4 = widget.fileArray.any((element) => '${element['url']}'.contains('mp4'));
  72. if(isMp4){
  73. allowedExtensions.remove('mp4');
  74. }
  75. FilePickerResult? result = await FilePicker.platform.pickFiles(
  76. type: FileType.custom,//'excel', 'word', 'pdf',
  77. allowedExtensions: allowedExtensions,
  78. );
  79. if(result!=null){
  80. LogUtil.d(result.files);
  81. if(result.files.isNotEmpty){
  82. Map fileMap = {};
  83. for (var element in result.files) {
  84. // if(element.size/1000000>20){
  85. // ysFlutterToast('文件不能超过20M');
  86. // return;
  87. // }
  88. fileMap['path'] = element.path;
  89. fileMap['name'] = element.name;
  90. }
  91. if('${fileMap['path']}'.contains('mp4')){
  92. widget.fileArray.insert(0, fileMap);
  93. }else{
  94. widget.fileArray.add(fileMap);
  95. }
  96. setState(() {});
  97. _postFileData(fileMap);
  98. }
  99. }
  100. }
  101. },
  102. child: index==0?Container(
  103. color: const Color(0xFF8A93A0),
  104. alignment: Alignment.center,
  105. child: Icon(Icons.file_copy,size: hsp(10),color: Colors.white,),
  106. ):Container(
  107. child: widget.fileArray[index-1]['url']!=null?Stack(
  108. children: [
  109. YSDocView(url: widget.fileArray[index-1]['url'],),
  110. Positioned(right: 0,top: 0,height: hsp(15),width: hsp(15),child: GestureDetector(
  111. onTap: (){
  112. widget.fileArray.removeAt(index-1);
  113. setState(() {});
  114. },
  115. behavior: HitTestBehavior.opaque,
  116. child: Container(
  117. decoration: const BoxDecoration(
  118. color: Colors.black54,
  119. borderRadius: BorderRadius.only(bottomLeft: Radius.circular(50))
  120. ),
  121. alignment: Alignment.topRight,
  122. padding: EdgeInsets.only(top: hsp(2),right: hsp(2)),
  123. child: Icon(Icons.close,size: hsp(8),color: Colors.white,),
  124. ),
  125. ),)
  126. ],
  127. ):widget.fileArray[index-1]['path']!=null?Stack(
  128. children: [
  129. YSDocView(url: widget.fileArray[index-1]['path'],),
  130. ClipRRect(
  131. child: Container(
  132. alignment: Alignment.center,
  133. height: conSize.maxWidth/2,
  134. width: conSize.maxWidth/2,
  135. child: CircularProgressIndicator(
  136. value: widget.fileArray[index-1]['rota'],
  137. color: Colors.black54,
  138. valueColor: const AlwaysStoppedAnimation(Colors.transparent),
  139. strokeWidth: conSize.maxWidth/6,
  140. ),
  141. ),
  142. ),
  143. if(widget.fileArray[index-1]['isError']==true)Container(
  144. color: Colors.black54,
  145. child: Stack(
  146. children: [
  147. GestureDetector(
  148. onTap: (){
  149. Map item = widget.fileArray[index-1];
  150. item.remove('isError');
  151. _postFileData(item);
  152. },
  153. behavior: HitTestBehavior.opaque,
  154. child: Container(
  155. alignment: Alignment.center,
  156. child: Text('上传失败\n重新上传',style: TextStyle(fontSize: zsp(8),color: const Color(0xFFACB5C5)),),
  157. ),
  158. ),
  159. Positioned(right: 0,top: 0,height: hsp(15),width: hsp(15),child: GestureDetector(
  160. onTap: (){
  161. widget.fileArray.removeAt(index-1);
  162. setState(() {});
  163. },
  164. behavior: HitTestBehavior.opaque,
  165. child: Container(
  166. decoration: const BoxDecoration(
  167. color: Colors.white60,
  168. borderRadius: BorderRadius.only(bottomLeft: Radius.circular(50))
  169. ),
  170. alignment: Alignment.topRight,
  171. padding: EdgeInsets.only(top: hsp(2),right: hsp(2)),
  172. child: Icon(Icons.close,size: hsp(8),color: Colors.black,),
  173. ),
  174. ),),
  175. ],
  176. ),
  177. )
  178. ],
  179. ):Container(),
  180. ),
  181. );
  182. },shrinkWrap: true,padding: const EdgeInsets.all(0),physics: const NeverScrollableScrollPhysics(),itemCount: widget.fileArray.length+1,);
  183. });
  184. }
  185. _postFileData(Map fileMap) async{
  186. FormData formData = FormData.fromMap(Map<String, dynamic>.from({}));
  187. formData.files.add(
  188. MapEntry('file', await MultipartFile.fromFile(fileMap['path'] ,filename: fileMap['name']))
  189. );
  190. if (!mounted) return;
  191. YSNetWork.ysRequestHttp2(context, type: RequestType.post, api: '/upload/${'${fileMap['path']}'.contains('mp4')==true?'video':'img'}',parameter: formData,imageSetter: (value){
  192. fileMap['rota'] = value;
  193. setState(() {});
  194. }, successSetter: (value) {
  195. if(value['msg']!=null){
  196. fileMap['isError'] = true;
  197. }else{
  198. Map data = value['data']??{};
  199. fileMap['url'] = data['img']??data['video']??'';
  200. }
  201. setState(() {});
  202. },isLoading: true);
  203. }
  204. }
  205. uploadFile(BuildContext context,ValueSetter valueSetter) async{
  206. List<String> allowedExtensions = ['jpg','jpeg','png'];
  207. FilePickerResult? result = await FilePicker.platform.pickFiles(
  208. type: FileType.custom,//'excel', 'word', 'pdf',
  209. allowedExtensions: allowedExtensions,
  210. );
  211. if(result!=null){
  212. LogUtil.d(result.files);
  213. if(result.files.isNotEmpty){
  214. Map fileMap = {};
  215. for (var element in result.files) {
  216. fileMap['path'] = element.path;
  217. fileMap['name'] = element.name;
  218. }
  219. FormData formData = FormData.fromMap(Map<String, dynamic>.from({}));
  220. formData.files.add(
  221. MapEntry('file', await MultipartFile.fromFile(fileMap['path'] ,filename: fileMap['name']))
  222. );
  223. // ignore: use_build_context_synchronously
  224. YSNetWork.ysRequestHttp2(context, type: RequestType.post, api: '/upload/${'${fileMap['path']}'.contains('mp4')==true?'video':'img'}',parameter: formData,imageSetter: (value){
  225. fileMap['rota'] = value;
  226. }, successSetter: (value) {
  227. if(value['msg']!=null){
  228. fileMap['isError'] = true;
  229. }else{
  230. Map data = value['data']??{};
  231. fileMap['url'] = data['img']??data['video']??'';
  232. valueSetter(fileMap);
  233. }
  234. });
  235. }
  236. }
  237. }
  238. class YSUploadFileView extends StatefulWidget {
  239. final bool isInvoice;
  240. final List fileArray;
  241. const YSUploadFileView({Key? key, required this.fileArray,this.isInvoice = false}) : super(key: key);
  242. @override
  243. YSUploadFileViewState createState() => YSUploadFileViewState();
  244. }
  245. class YSUploadFileViewState extends State<YSUploadFileView> {
  246. bool _isInvoice = false;
  247. @override
  248. void initState() {
  249. _isInvoice = widget.isInvoice;
  250. super.initState();
  251. }
  252. @override
  253. Widget build(BuildContext context) {
  254. return LayoutBuilder(builder: (context,conSize){
  255. return GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  256. crossAxisCount: 4,
  257. childAspectRatio: 54/35,
  258. crossAxisSpacing: hsp(15),
  259. mainAxisSpacing: hsp(15)
  260. ), itemBuilder: (context,index){
  261. return GestureDetector(
  262. onTap: (){
  263. FocusScope.of(context).unfocus();
  264. if(index==0){
  265. if(_isInvoice&&widget.fileArray.isNotEmpty)return;
  266. ysShowBottomAlertView(context, YSChooseFileView(valueSetter: (fileMap) async{
  267. bool isInvoice = fileMap['invoice']??false;
  268. _isInvoice = isInvoice;
  269. int type = fileMap['type']??1;
  270. var value = fileMap['value'];
  271. if(value is List){
  272. List valueArray = value;
  273. for (var element in valueArray) {
  274. Map fileMap = {'path':element.path,'name':element.name,'type':type};
  275. widget.fileArray.add(fileMap);
  276. setState(() {});
  277. _postFileData(fileMap);
  278. }
  279. }else{
  280. Map fileMap = {'path':value.path,'name':value.name,'type':type};
  281. widget.fileArray.add(fileMap);
  282. setState(() {});
  283. _postFileData(fileMap);
  284. }
  285. },isPhoto: widget.isInvoice,),isBarr: true);
  286. }
  287. },
  288. child: index==0?Container(
  289. color: const Color(0xFFF7F8FA),
  290. alignment: Alignment.center,
  291. child: Icon(Icons.camera_alt,size: hsp(20),color: const Color(0xFFDCDEE0),),
  292. ):Container(
  293. child: widget.fileArray[index-1]['url']!=null?Stack(
  294. children: [
  295. widget.fileArray[index-1]['type']!=1?YSVideoView(
  296. url: widget.fileArray[index-1]['url']
  297. ):YSImageView(url: widget.fileArray[index-1]['url'],),
  298. Positioned(right: 0,top: 0,height: hsp(30),width: hsp(30),child: GestureDetector(
  299. onTap: (){
  300. widget.fileArray.removeAt(index-1);
  301. setState(() {});
  302. },
  303. behavior: HitTestBehavior.opaque,
  304. child: Container(
  305. decoration: const BoxDecoration(
  306. color: Colors.black54,
  307. borderRadius: BorderRadius.only(bottomLeft: Radius.circular(50))
  308. ),
  309. alignment: Alignment.topRight,
  310. padding: EdgeInsets.only(top: hsp(2),right: hsp(2)),
  311. child: Icon(Icons.close,size: hsp(20),color: Colors.white,),
  312. ),
  313. ),)
  314. ],
  315. ):widget.fileArray[index-1]['path']!=null?Stack(
  316. children: [
  317. '${widget.fileArray[index-1]['path']}'.contains('mp4')?YSVideoView(
  318. url: widget.fileArray[index-1]['path']
  319. ):YSImageView(url: widget.fileArray[index-1]['path'],),
  320. Container(
  321. padding: EdgeInsets.all(hsp(25)),
  322. height: 100,
  323. width: 100,
  324. child: CircularProgressIndicator(
  325. value: widget.fileArray[index-1]['rota'],
  326. color: Colors.lightBlueAccent,
  327. backgroundColor: Colors.white,
  328. strokeWidth: 4,
  329. ),
  330. )
  331. ],
  332. ):Container(),
  333. ),
  334. );
  335. },shrinkWrap: true,padding: const EdgeInsets.all(0),physics: const NeverScrollableScrollPhysics(),itemCount: widget.fileArray.length+1,);
  336. });
  337. }
  338. _postFileData(Map fileMap) async{
  339. FormData formData = FormData.fromMap(Map<String, dynamic>.from({}));
  340. formData.files.add(
  341. MapEntry('file', await MultipartFile.fromFile(fileMap['path'] ,filename: fileMap['name']))
  342. );
  343. if (!mounted) return;
  344. YSNetWork.ysRequestHttp2(context, type: RequestType.post, api: 'file/upload',parameter: formData,imageSetter: (value){
  345. fileMap['rota'] = value;
  346. setState(() {});
  347. }, successSetter: (value) {
  348. List data = value['data']??[];
  349. for (var element in data) {
  350. fileMap['url'] = element['filePath'];
  351. }
  352. setState(() {});
  353. if(_isInvoice){
  354. YSNetWork.ysRequestHttp(context, type: RequestType.post, api: 'energyConsumptionOil/appCheckInvoice', parameter: {
  355. 'check':fileMap['url']
  356. }, successSetter: (dict){
  357. Map info = dict['data'];
  358. CustomerValueNotification(info).dispatch(context);
  359. });
  360. }
  361. LogUtil.d(fileMap);
  362. });
  363. }
  364. }
  365. class YSDocView extends StatefulWidget {
  366. final String url;
  367. const YSDocView({Key? key, required this.url}) : super(key: key);
  368. @override
  369. YSDocViewState createState() => YSDocViewState();
  370. }
  371. class YSDocViewState extends State<YSDocView> {
  372. @override
  373. void initState() {
  374. super.initState();
  375. }
  376. @override
  377. Widget build(BuildContext context) {
  378. return widget.url.contains('.png')||widget.url.contains('.jpg')||widget.url.contains('.jpeg')?YSImageView(
  379. url: widget.url
  380. ):widget.url.contains('.mp4')?YSVideoView(
  381. url: widget.url
  382. ):GestureDetector(
  383. onTap: (){
  384. // return;
  385. Navigator.of(context).push(
  386. CupertinoPageRoute(builder: (context){
  387. return YSDocDetailView(path: widget.url);
  388. })
  389. );
  390. },
  391. child: Container(
  392. alignment: Alignment.center,
  393. child: Icon(Icons.insert_drive_file_sharp,color: Colors.orange,size: hsp(60),),
  394. ),
  395. );
  396. }
  397. }
  398. class YSDocDetailView extends StatelessWidget {
  399. final String path;
  400. const YSDocDetailView({Key? key, required this.path}) : super(key: key);
  401. @override
  402. Widget build(BuildContext context) {
  403. return YSBase(
  404. ysTitle: '文件预览',
  405. ysColor: Colors.white,
  406. ysChild: SizedBox(
  407. height: ysHeight(context),
  408. width: ysWidth(context),
  409. child: FilePreviewWidget(
  410. width: ysHeight(context),//宽
  411. height: ysWidth(context),//高
  412. callBack: FilePreviewCallBack(onShow: () {
  413. LogUtil.d("文件打开成功");
  414. }, onDownload: (progress) {
  415. LogUtil.d("文件下载进度$progress");
  416. }, onFail: (code, msg) {
  417. LogUtil.d("文件打开失败 $code $msg");
  418. }),
  419. path: path,//本地路径或者http链接
  420. ),
  421. ),
  422. );
  423. }
  424. }
  425. class YSImageView extends StatelessWidget {
  426. final String url;
  427. const YSImageView({Key? key, required this.url}) : super(key: key);
  428. @override
  429. Widget build(BuildContext context) {
  430. return GestureDetector(
  431. onTap: (){
  432. Navigator.of(context).push(
  433. CupertinoPageRoute(builder: (context){
  434. return YSPreviewImageView(url: url.contains('carbon')==true?'$fileUrl$url':url);
  435. })
  436. );
  437. },
  438. child: url.contains('carbon')?Image.network(
  439. '$fileUrl$url',
  440. fit: BoxFit.cover,
  441. width: double.infinity,
  442. height: double.infinity,
  443. ):Image.file(
  444. File(url),
  445. fit: BoxFit.cover,
  446. width: double.infinity,
  447. height: double.infinity,
  448. ),
  449. );
  450. }
  451. }
  452. class YSVideoView extends StatefulWidget {
  453. final String url;
  454. const YSVideoView({Key? key, required this.url}) : super(key: key);
  455. @override
  456. YSVideoViewState createState() => YSVideoViewState();
  457. }
  458. class YSVideoViewState extends State<YSVideoView> {
  459. @override
  460. void initState() {
  461. super.initState();
  462. _getImage();
  463. }
  464. _getImage() async{
  465. final uint8List = await VideoThumbnail.thumbnailData(
  466. video: widget.url,
  467. imageFormat: ImageFormat.JPEG,
  468. );
  469. YSData().image = Image.memory(uint8List!,fit: BoxFit.fill,height: double.infinity,width: double.infinity,);
  470. }
  471. @override
  472. Widget build(BuildContext context) {
  473. return GestureDetector(
  474. onTap: (){
  475. if(widget.url.contains('carbon')){
  476. Navigator.of(context).push(
  477. CupertinoPageRoute(builder: (context){
  478. return YSVideoHorizontal(url: '$fileUrl${widget.url}');
  479. })
  480. );
  481. }
  482. },
  483. behavior: HitTestBehavior.opaque,
  484. child: Center(
  485. child: Stack(
  486. alignment: Alignment.center,
  487. children: [
  488. YSData().image,
  489. if(widget.url.contains('carbon'))Center(
  490. child: Icon(Icons.play_circle_fill,color: Colors.white,size: hsp(20),),
  491. )
  492. ],
  493. ),
  494. ),
  495. )
  496. ;
  497. }
  498. }
  499. class YSPreviewImageView extends StatelessWidget {
  500. final String url;
  501. const YSPreviewImageView({Key? key, required this.url}) : super(key: key);
  502. @override
  503. Widget build(BuildContext context) {
  504. return GestureDetector(
  505. onTap: (){
  506. Navigator.pop(context);
  507. },
  508. child: Container(
  509. height: ysHeight(context),
  510. width: ysHeight(context),
  511. color: Colors.black,
  512. child: url.contains('http')?Image.network(
  513. url,
  514. fit: BoxFit.cover,
  515. width: double.infinity,
  516. height: double.infinity,
  517. ):Image.file(
  518. File(url),
  519. fit: BoxFit.cover,
  520. width: double.infinity,
  521. height: double.infinity,
  522. ),
  523. ),
  524. );
  525. }
  526. }
  527. class YSVideoHorizontal extends StatefulWidget {
  528. final String url;
  529. final String title;
  530. const YSVideoHorizontal({Key? key, required this.url, this.title = ''}) : super(key: key);
  531. @override
  532. YSVideoHorizontalState createState() => YSVideoHorizontalState();
  533. }
  534. class YSVideoHorizontalState extends State<YSVideoHorizontal> {
  535. late StateSetter _playSet,_progressSet;
  536. String _startTime = '00:00:00';
  537. String _endTime = '00:00:00';
  538. late VideoPlayerController _controller;
  539. @override
  540. void initState() {
  541. // SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
  542. // SystemChrome.setPreferredOrientations([
  543. // DeviceOrientation.landscapeLeft, //全屏时旋转方向,左边
  544. // ]);
  545. _getPlayer();
  546. super.initState();
  547. }
  548. _getPlayer() {
  549. // LogUtil.d(widget.url);
  550. //https://media.w3.org/2010/05/sintel/trailer.mp4
  551. if(widget.url.contains('http')){
  552. _controller = VideoPlayerController.network(widget.url)..initialize().then((_) {
  553. _controller.play();
  554. setState(() {});
  555. })..addListener(() {
  556. Duration duration = _controller.value.duration;
  557. Duration position = _controller.value.position;
  558. _endTime = '${'${duration.inHours}'.padLeft(2,'0')}:${'${duration.inMinutes}'.padLeft(2,'0')}:${'${duration.inSeconds}'.padLeft(2,'0')}';
  559. _startTime = '${'${position.inHours}'.padLeft(2,'0')}:${'${position.inMinutes}'.padLeft(2,'0')}:${'${position.inSeconds}'.padLeft(2,'0')}';
  560. if(mounted){
  561. _progressSet(() {});
  562. }
  563. });
  564. }else{
  565. _controller = VideoPlayerController.file(File(widget.url))..initialize().then((_) {
  566. _controller.play();
  567. setState(() {});
  568. })..addListener(() {
  569. Duration duration = _controller.value.duration;
  570. Duration position = _controller.value.position;
  571. _endTime = '${'${duration.inHours}'.padLeft(2,'0')}:${'${duration.inMinutes}'.padLeft(2,'0')}:${'${duration.inSeconds}'.padLeft(2,'0')}';
  572. _startTime = '${'${position.inHours}'.padLeft(2,'0')}:${'${position.inMinutes}'.padLeft(2,'0')}:${'${position.inSeconds}'.padLeft(2,'0')}';
  573. if(mounted){
  574. _progressSet(() {});
  575. }
  576. });
  577. }
  578. }
  579. @override
  580. void dispose() {
  581. _controller.dispose();
  582. // SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);
  583. // SystemChrome.setPreferredOrientations([
  584. // DeviceOrientation.portraitUp,
  585. // ]);
  586. super.dispose();
  587. }
  588. @override
  589. Widget build(BuildContext context) {
  590. return Scaffold(
  591. backgroundColor: Colors.black,
  592. body: SizedBox(
  593. height: ysHeight(context),
  594. width: ysWidth(context),
  595. child: Stack(
  596. children: <Widget>[
  597. _controller.value.aspectRatio<1?Center(
  598. child: AspectRatio(
  599. aspectRatio: _controller.value.aspectRatio,
  600. child: VideoPlayer(_controller),
  601. ),
  602. ):VideoPlayer(_controller),
  603. _pauseView(controller: _controller),
  604. Container(
  605. width: ysWidth(context),
  606. height: hsp(30),
  607. margin: EdgeInsets.only(left: hsp(15),right: hsp(35),top: ysTOP(context)+hsp(10)),
  608. child: Row(
  609. children: [
  610. GestureDetector(
  611. onTap: (){Navigator.pop(context);},
  612. child: Icon(Icons.chevron_left,size: hsp(30),color: Colors.white,),
  613. ),
  614. SizedBox(
  615. width: ysWidth(context)-hsp(80),
  616. child: Text(widget.title,style: TextStyle(fontSize: zsp(16),color: Colors.white),),
  617. )
  618. ],
  619. ),
  620. ),
  621. StatefulBuilder(
  622. builder: (context,progressSet){
  623. _progressSet = progressSet;
  624. return Container(
  625. margin: EdgeInsets.only(top: ysHeight(context)-hsp(50),left: hsp(15),right: hsp(15)),
  626. child: Row(
  627. children: [
  628. SizedBox(
  629. width: hsp(100),
  630. child: Row(
  631. children: [
  632. GestureDetector(
  633. onTap: (){
  634. _playSet(() {
  635. _controller.value.isPlaying?_controller.pause() : _controller.play();
  636. });
  637. progressSet(() {});
  638. },
  639. child: Icon(_controller.value.isPlaying?Icons.pause:Icons.play_arrow,size: hsp(25),color: Colors.white,),
  640. ),
  641. Container(
  642. alignment: Alignment.center,
  643. width: hsp(75),
  644. child: Text(_startTime,style: TextStyle(fontSize: zsp(12),color: Colors.white),),
  645. )
  646. ],
  647. ),
  648. ),
  649. SizedBox(
  650. width: ysWidth(context)-hsp(230),
  651. height:6.5,
  652. child: VideoProgressIndicator(
  653. _controller,
  654. allowScrubbing: true,
  655. colors: const VideoProgressColors(playedColor: Colors.white,backgroundColor: Colors.black),
  656. )
  657. ),
  658. SizedBox(
  659. width: hsp(100),
  660. child: Row(
  661. children: [
  662. Container(
  663. alignment: Alignment.center,
  664. width: hsp(75),
  665. child: Text(_endTime,style: TextStyle(fontSize: zsp(12),color: Colors.white),),
  666. ),
  667. GestureDetector(
  668. onTap: (){Navigator.pop(context);},
  669. child: Icon(Icons.api,size: hsp(20),color: Colors.white,),
  670. )
  671. ],
  672. )
  673. ),
  674. ],
  675. ),
  676. );
  677. },
  678. ),
  679. ],
  680. ),
  681. ),
  682. );
  683. }
  684. _pauseView({required VideoPlayerController controller}) {
  685. return StatefulBuilder(
  686. builder: (context,playSet){
  687. _playSet = playSet;
  688. return Stack(
  689. children: <Widget>[
  690. AnimatedSwitcher(
  691. duration: const Duration(milliseconds: 50),
  692. reverseDuration: const Duration(milliseconds: 200),
  693. child: controller.value.isPlaying? Container():Container(
  694. alignment: Alignment.center,
  695. color: Colors.transparent,
  696. child: const Icon(
  697. Icons.play_circle_filled,
  698. color: Colors.white,
  699. size: 50,
  700. ),
  701. ),
  702. ),
  703. GestureDetector(
  704. onTap: () {
  705. playSet(() {
  706. controller.value.isPlaying ? controller.pause() : controller.play();
  707. });
  708. _progressSet(() {});
  709. },
  710. ),
  711. ],
  712. );
  713. },
  714. );
  715. }
  716. }