Reason Pun

增加视频录制和播放页面功能,增加清栈和提示

...@@ -3,6 +3,8 @@ import 'package:flutter/material.dart'; ...@@ -3,6 +3,8 @@ import 'package:flutter/material.dart';
3 import 'package:one_poem/res/constant.dart'; 3 import 'package:one_poem/res/constant.dart';
4 import 'package:one_poem/routers/fluro_navigator.dart'; 4 import 'package:one_poem/routers/fluro_navigator.dart';
5 5
6 +import 'package:one_poem/extension/int_extension.dart';
7 +
6 /// 创建人: Created by zhaolong 8 /// 创建人: Created by zhaolong
7 /// 创建时间:Created by on 2020/12/12. 9 /// 创建时间:Created by on 2020/12/12.
8 /// 10 ///
...@@ -11,7 +13,6 @@ import 'package:one_poem/routers/fluro_navigator.dart'; ...@@ -11,7 +13,6 @@ import 'package:one_poem/routers/fluro_navigator.dart';
11 /// 可关注博客:https://blog.csdn.net/zl18603543572 13 /// 可关注博客:https://blog.csdn.net/zl18603543572
12 /// 14 ///
13 /// 代码清单 15 /// 代码清单
14 -///代码清单
15 class ProtocolModel { 16 class ProtocolModel {
16 late TapGestureRecognizer _registerProtocolRecognizer; 17 late TapGestureRecognizer _registerProtocolRecognizer;
17 late TapGestureRecognizer _privacyProtocolRecognizer; 18 late TapGestureRecognizer _privacyProtocolRecognizer;
...@@ -23,7 +24,6 @@ class ProtocolModel { ...@@ -23,7 +24,6 @@ class ProtocolModel {
23 //隐私协议的手势 24 //隐私协议的手势
24 _privacyProtocolRecognizer = TapGestureRecognizer(); 25 _privacyProtocolRecognizer = TapGestureRecognizer();
25 26
26 - //苹果风格弹框
27 bool isShow = await showDialog( 27 bool isShow = await showDialog(
28 //上下文对象 28 //上下文对象
29 context: context, 29 context: context,
...@@ -40,12 +40,12 @@ class ProtocolModel { ...@@ -40,12 +40,12 @@ class ProtocolModel {
40 return Future.value(isShow); 40 return Future.value(isShow);
41 } 41 }
42 42
43 - AlertDialog showAlertDialog(BuildContext context) { 43 + AlertDialog showAlertDialog(BuildContext context) {
44 return AlertDialog( 44 return AlertDialog(
45 title: const Text("温馨提示"), 45 title: const Text("温馨提示"),
46 content: Container( 46 content: Container(
47 - height: 260, 47 + height: 260.px,
48 - padding: const EdgeInsets.all(1), 48 + padding: EdgeInsets.all(1.px),
49 //可滑动布局 49 //可滑动布局
50 child: SingleChildScrollView( 50 child: SingleChildScrollView(
51 child: buildContent(context), 51 child: buildContent(context),
...@@ -71,7 +71,6 @@ class ProtocolModel { ...@@ -71,7 +71,6 @@ class ProtocolModel {
71 //协议说明文案 71 //协议说明文案
72 String userPrivateProtocol = 72 String userPrivateProtocol =
73 "我们一向尊重并会严格保护用户在使用本产品时的合法权益(包括用户隐私、用户数据等)不受到任何侵犯。本协议(包括本文最后部分的隐私政策)是用户(包括通过各种合法途径获取到本产品的自然人、法人或其他组织机构,以下简称“用户”或“您”)与我们之间针对本产品相关事项最终的、完整的且排他的协议,并取代、合并之前的当事人之间关于上述事项的讨论和协议。本协议将对用户使用本产品的行为产生法律约束力,您已承诺和保证有权利和能力订立本协议。用户开始使用本产品将视为已经接受本协议,请认真阅读并理解本协议中各种条款,包括免除和限制我们的免责条款和对用户的权利限制(未成年人审阅时应由法定监护人陪同),如果您不能接受本协议中的全部条款,请勿开始使用本产品"; 73 "我们一向尊重并会严格保护用户在使用本产品时的合法权益(包括用户隐私、用户数据等)不受到任何侵犯。本协议(包括本文最后部分的隐私政策)是用户(包括通过各种合法途径获取到本产品的自然人、法人或其他组织机构,以下简称“用户”或“您”)与我们之间针对本产品相关事项最终的、完整的且排他的协议,并取代、合并之前的当事人之间关于上述事项的讨论和协议。本协议将对用户使用本产品的行为产生法律约束力,您已承诺和保证有权利和能力订立本协议。用户开始使用本产品将视为已经接受本协议,请认真阅读并理解本协议中各种条款,包括免除和限制我们的免责条款和对用户的权利限制(未成年人审阅时应由法定监护人陪同),如果您不能接受本协议中的全部条款,请勿开始使用本产品";
74 -
75 buildContent(BuildContext context) { 74 buildContent(BuildContext context) {
76 return RichText( 75 return RichText(
77 text: TextSpan( 76 text: TextSpan(
......
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:one_poem/res/resources.dart'; 2 import 'package:one_poem/res/resources.dart';
3 +import 'package:one_poem/routers/fluro_navigator.dart';
4 +import 'package:one_poem/routers/routers.dart';
3 import 'package:one_poem/util/toast_utils.dart'; 5 import 'package:one_poem/util/toast_utils.dart';
4 import 'package:one_poem/widgets/my_app_bar.dart'; 6 import 'package:one_poem/widgets/my_app_bar.dart';
5 7
8 +import 'package:one_poem/extension/int_extension.dart';
9 +
6 class PoemPublish extends StatefulWidget { 10 class PoemPublish extends StatefulWidget {
7 const PoemPublish({Key? key, required this.data}) : super(key: key); 11 const PoemPublish({Key? key, required this.data}) : super(key: key);
8 12
...@@ -24,124 +28,158 @@ class _PoemPublishState extends State<PoemPublish> { ...@@ -24,124 +28,158 @@ class _PoemPublishState extends State<PoemPublish> {
24 28
25 @override 29 @override
26 Widget build(BuildContext context) { 30 Widget build(BuildContext context) {
27 - return Scaffold( 31 + return WillPopScope(
28 - appBar: MyAppBar( 32 + onWillPop: _isExit,
29 - homeMenuHeader: Container( 33 + child: Scaffold(
30 - alignment: Alignment.center, 34 + appBar: MyAppBar(
31 - width: double.infinity, 35 + homeMenuHeader: Container(
32 - child: const Text( 36 + alignment: Alignment.center,
33 - "发布临境", 37 + width: double.infinity,
34 - style: TextStyle( 38 + child: const Text(
35 - color: Colors.white, 39 + "发布临境",
40 + style: TextStyle(
41 + color: Colors.white,
42 + ),
36 ), 43 ),
37 ), 44 ),
38 ), 45 ),
39 - ), 46 + body: Column(
40 - body: Column( 47 + crossAxisAlignment: CrossAxisAlignment.start,
41 - crossAxisAlignment: CrossAxisAlignment.start, 48 + children: <Widget>[
42 - children: <Widget>[ 49 + Padding(
43 - Padding( 50 + padding: const EdgeInsets.all(
44 - padding: const EdgeInsets.all( 51 + 10.0,
45 - 10.0,
46 - ),
47 - child: ConstrainedBox(
48 - constraints: const BoxConstraints(
49 - maxHeight: 200,
50 - maxWidth: double.infinity,
51 ), 52 ),
52 - child: TextField( 53 + child: ConstrainedBox(
53 - maxLines: 10, 54 + constraints: const BoxConstraints(
54 - decoration: InputDecoration( 55 + maxHeight: 200,
55 - contentPadding: const EdgeInsets.all(10.0), 56 + maxWidth: double.infinity,
56 - hintText: '读此一言,仿佛身临其境',
57 - border: OutlineInputBorder(
58 - borderRadius: BorderRadius.circular(5),
59 - borderSide: BorderSide.none),
60 - filled: true,
61 - fillColor: Colors.grey.shade100,
62 - ),
63 - ),
64 - ),
65 - ),
66 - Container(
67 - padding: const EdgeInsets.all(10.0),
68 - alignment: Alignment.centerLeft,
69 - width: double.infinity,
70 - height: 36.0,
71 - child: Wrap(
72 - children: const [
73 - Icon(
74 - Icons.room_outlined,
75 - size: 15,
76 ), 57 ),
77 - Text( 58 + child: TextField(
78 - "我在此地", 59 + maxLines: 10,
79 - style: TextStyle(color: Colors.black45), 60 + decoration: InputDecoration(
61 + contentPadding: const EdgeInsets.all(10.0),
62 + hintText: '读此一言,仿佛身临其境',
63 + border: OutlineInputBorder(
64 + borderRadius: BorderRadius.circular(5),
65 + borderSide: BorderSide.none),
66 + filled: true,
67 + fillColor: Colors.grey.shade100,
68 + ),
80 ), 69 ),
81 - ], 70 + ),
82 ), 71 ),
83 - ), 72 + Container(
84 - Container( 73 + padding: EdgeInsets.all(10.px),
85 - padding: const EdgeInsets.all(10.0), 74 + alignment: Alignment.centerLeft,
86 - alignment: Alignment.centerLeft, 75 + width: double.infinity,
87 - width: double.infinity, 76 + height: 36.px,
88 - height: 36.0, 77 + child: Wrap(
89 - child: Wrap( 78 + children: [
90 - children: const [ 79 + Icon(
91 - Icon( 80 + Icons.room_outlined,
92 - Icons.room_outlined, 81 + size: 15.px,
93 - size: 15, 82 + ),
94 - ), 83 + Gaps.hGap5,
95 - Text( 84 + const Text(
96 - "所用口音", 85 + "我在此地",
97 - style: TextStyle(color: Colors.black45), 86 + style: TextStyle(color: Colors.black45),
98 - ), 87 + ),
99 - Gaps.hGap10, 88 + ],
100 - Text( 89 + ),
101 - "普通话",
102 - style: TextStyle(color: Colors.black45),
103 - ),
104 - ],
105 ), 90 ),
106 - ), 91 + Container(
107 - Gaps.vGap24, 92 + padding: EdgeInsets.all(10.px),
108 - Expanded( 93 + alignment: Alignment.centerLeft,
109 - child: Column( 94 + width: double.infinity,
110 - crossAxisAlignment: CrossAxisAlignment.center, 95 + height: 36.px,
111 - children: [ 96 + child: Wrap(
112 - Container( 97 + children: [
113 - height: 36.0, 98 + Icon(
114 - alignment: Alignment.center, 99 + Icons.record_voice_over_outlined,
115 - width: double.infinity, 100 + size: 15.px,
116 - child: const Text(
117 - "发布临境,让更多人身临其境",
118 - style: TextStyle(fontSize: 12.0),
119 ), 101 ),
120 - ), 102 + Gaps.hGap5,
121 - Container( 103 + const Text(
122 - height: 48.0, 104 + "所用口音",
123 - alignment: Alignment.center, 105 + style: TextStyle(color: Colors.black45),
124 - width: double.infinity, 106 + ),
125 - child: TextButton( 107 + Gaps.hGap10,
126 - style: ButtonStyle( 108 + const Text(
127 - side: MaterialStateProperty.all( 109 + "普通话",
128 - const BorderSide(color: Colors.black54, width: 1), 110 + style: TextStyle(color: Colors.black45),
129 - ), 111 + ),
112 + ],
113 + ),
114 + ),
115 + const Spacer(),
116 + Expanded(
117 + child: Center(
118 + child: Column(
119 + crossAxisAlignment: CrossAxisAlignment.center,
120 + mainAxisAlignment: MainAxisAlignment.center,
121 + children: [
122 + Text(
123 + "发布临境,让更多人身临其境",
124 + style: TextStyle(fontSize: 14.px),
130 ), 125 ),
131 - onPressed: () { 126 + Gaps.vGap10,
132 - Toast.show("先不发布了吧。。。。"); 127 + TextButton(
133 - }, 128 + style: ButtonStyle(
134 - child: const Text( 129 + side: MaterialStateProperty.all(
135 - "发布", 130 + BorderSide(
136 - style: TextStyle(color: Colors.black54, fontSize: 15.0), 131 + color: Colors.black54,
132 + width: 1.px,
133 + ),
134 + ),
135 + ),
136 + onPressed: () {
137 + Toast.show("先不发布了吧。。。。");
138 + },
139 + child: Text(
140 + "发布",
141 + style:
142 + TextStyle(color: Colors.black54, fontSize: 15.px),
143 + ),
137 ), 144 ),
138 - ), 145 + ],
139 ), 146 ),
140 - ], 147 + ),
141 ), 148 ),
142 - ), 149 + ],
143 - ], 150 + ),
144 ), 151 ),
145 ); 152 );
146 } 153 }
154 +
155 + Future<bool> _isExit() async {
156 + showDialog(
157 + context: context,
158 + builder: (BuildContext context) {
159 + return AlertDialog(
160 + title: const Text("温馨提示"),
161 + content: Container(
162 + padding: EdgeInsets.all(1.px),
163 + //可滑动布局
164 + child: const Text("确认放弃此次作品吗?"),
165 + ),
166 + actions: [
167 + TextButton(
168 + child: const Text("再想想"),
169 + onPressed: () {
170 + Navigator.of(context).pop(true);
171 + },
172 + ),
173 + TextButton(
174 + child: const Text("残忍放弃"),
175 + onPressed: () {
176 + NavigatorUtils.push(context, Routes.home, clearStack: true);
177 + },
178 + ),
179 + ],
180 + );
181 + },
182 + );
183 + return Future.value(false);
184 + }
147 } 185 }
......
...@@ -4,6 +4,8 @@ import 'dart:io'; ...@@ -4,6 +4,8 @@ import 'dart:io';
4 import 'package:camera/camera.dart'; 4 import 'package:camera/camera.dart';
5 import 'package:flutter/material.dart'; 5 import 'package:flutter/material.dart';
6 import 'package:flutter/services.dart'; 6 import 'package:flutter/services.dart';
7 +import 'package:one_poem/res/resources.dart';
8 +import 'package:one_poem/routers/fluro_navigator.dart';
7 import 'package:one_poem/util/toast_utils.dart'; 9 import 'package:one_poem/util/toast_utils.dart';
8 import 'package:one_poem/widgets/my_app_bar.dart'; 10 import 'package:one_poem/widgets/my_app_bar.dart';
9 import 'package:path_provider/path_provider.dart'; 11 import 'package:path_provider/path_provider.dart';
...@@ -11,6 +13,8 @@ import 'package:pausable_timer/pausable_timer.dart'; ...@@ -11,6 +13,8 @@ import 'package:pausable_timer/pausable_timer.dart';
11 import 'package:video_player/video_player.dart'; 13 import 'package:video_player/video_player.dart';
12 import 'package:one_poem/extension/int_extension.dart'; 14 import 'package:one_poem/extension/int_extension.dart';
13 15
16 +import '../poem_router.dart';
17 +
14 class PoemRecordVideoPage extends StatefulWidget { 18 class PoemRecordVideoPage extends StatefulWidget {
15 const PoemRecordVideoPage({Key? key}) : super(key: key); 19 const PoemRecordVideoPage({Key? key}) : super(key: key);
16 20
...@@ -44,7 +48,7 @@ class _PoemRecordVideoPageState extends State<PoemRecordVideoPage> ...@@ -44,7 +48,7 @@ class _PoemRecordVideoPageState extends State<PoemRecordVideoPage>
44 ///记录当前的时间 48 ///记录当前的时间
45 int currentTimer = 0; 49 int currentTimer = 0;
46 50
47 - int duration = 60 * 1000; 51 + int duration = 10 * 1000; //TODO 60 * 1000;
48 52
49 @override 53 @override
50 void initState() { 54 void initState() {
...@@ -244,19 +248,19 @@ class _PoemRecordVideoPageState extends State<PoemRecordVideoPage> ...@@ -244,19 +248,19 @@ class _PoemRecordVideoPageState extends State<PoemRecordVideoPage>
244 try { 248 try {
245 XFile? rawVideo = await stopVideoRecording(); 249 XFile? rawVideo = await stopVideoRecording();
246 File videoFile = File(rawVideo!.path); 250 File videoFile = File(rawVideo!.path);
247 -
248 int currentUnix = DateTime.now().millisecondsSinceEpoch; 251 int currentUnix = DateTime.now().millisecondsSinceEpoch;
249 -
250 final directory = await getApplicationDocumentsDirectory(); 252 final directory = await getApplicationDocumentsDirectory();
251 -
252 String fileFormat = videoFile.path.split('.').last; 253 String fileFormat = videoFile.path.split('.').last;
253 -
254 _videoFile = await videoFile.copy( 254 _videoFile = await videoFile.copy(
255 '${directory.path}/$currentUnix.$fileFormat', 255 '${directory.path}/$currentUnix.$fileFormat',
256 ); 256 );
257 -
258 // TODO why pause!直接使用cancel()会出现问题,暂时这么解决 257 // TODO why pause!直接使用cancel()会出现问题,暂时这么解决
259 _timer.pause(); 258 _timer.pause();
259 +
260 + NavigatorUtils.push(
261 + context,
262 + '${PoemRouter.poemVideoPlayer}?url=100',
263 + );
260 } catch (e) { 264 } catch (e) {
261 // print(e); 265 // print(e);
262 } 266 }
...@@ -276,13 +280,49 @@ class _PoemRecordVideoPageState extends State<PoemRecordVideoPage> ...@@ -276,13 +280,49 @@ class _PoemRecordVideoPageState extends State<PoemRecordVideoPage>
276 controller!.buildPreview(), 280 controller!.buildPreview(),
277 Padding( 281 Padding(
278 padding: EdgeInsets.fromLTRB(10.px, 30.px, 10.px, 10.px), 282 padding: EdgeInsets.fromLTRB(10.px, 30.px, 10.px, 10.px),
279 - child: Text( 283 + child: Column(
280 - "清晨入古寺,\n初日照高林。\n曲径通幽处,\n禅房花木深。\n山光悦鸟性,\n潭影空人心。\n万籁此都寂,\n但余钟磬音。\n", 284 + crossAxisAlignment: CrossAxisAlignment.start,
281 - style: TextStyle( 285 + children: [
282 - color: Colors.white, 286 + Text(
283 - fontFamily: "ZCOOLXiaoWei", 287 + "题破山寺后禅院",
284 - fontSize: 20.px, 288 + style: TextStyle(
285 - ), 289 + color: Colors.white,
290 + fontSize: 28.px,
291 + ),
292 + ),
293 + Gaps.vGap10,
294 + Text(
295 + "常建",
296 + style: TextStyle(
297 + color: Colors.white,
298 + fontSize: 15.px,
299 + ),
300 + ),
301 + Gaps.vGap5,
302 + Text(
303 + "清晨入古寺,\n初日照高林。\n曲径通幽处,\n禅房花木深。\n山光悦鸟性,\n潭影空人心。\n万籁此都寂,\n但余钟磬音。\n",
304 + style: TextStyle(
305 + color: Colors.white,
306 + fontFamily: "ZCOOLXiaoWei",
307 + fontSize: 25.px,
308 + ),
309 + ),
310 + Gaps.vGap5,
311 + Text(
312 + "临者:老魔取西经",
313 + style: TextStyle(
314 + color: Colors.white,
315 + fontSize: 15.px,
316 + ),
317 + ),
318 + Text(
319 + "2022年01月25日 辰时三刻",
320 + style: TextStyle(
321 + color: Colors.white,
322 + fontSize: 15.px,
323 + ),
324 + ),
325 + ],
286 ), 326 ),
287 ), 327 ),
288 Padding( 328 Padding(
......
1 import 'package:fijkplayer/fijkplayer.dart'; 1 import 'package:fijkplayer/fijkplayer.dart';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 +import 'package:one_poem/res/resources.dart';
4 +import 'package:one_poem/routers/fluro_navigator.dart';
3 import 'package:one_poem/widgets/my_app_bar.dart'; 5 import 'package:one_poem/widgets/my_app_bar.dart';
6 +import 'package:one_poem/extension/int_extension.dart';
7 +
8 +import '../poem_router.dart';
4 9
5 class PoemVideoPlayer extends StatefulWidget { 10 class PoemVideoPlayer extends StatefulWidget {
6 final String url; 11 final String url;
...@@ -26,7 +31,11 @@ class _PoemVideoPlayerState extends State<PoemVideoPlayer> { ...@@ -26,7 +31,11 @@ class _PoemVideoPlayerState extends State<PoemVideoPlayer> {
26 super.initState(); 31 super.initState();
27 // player.setDataSource(widget.url, autoPlay: true); 32 // player.setDataSource(widget.url, autoPlay: true);
28 //TODO 替换真实URL 33 //TODO 替换真实URL
29 - player.setDataSource("asset:///assets/data/video_01.mp4", autoPlay: true); 34 + player.setDataSource(
35 + "asset:///assets/data/video_01.mp4",
36 + autoPlay: true,
37 + );
38 + player.setLoop(0);
30 } 39 }
31 40
32 @override 41 @override
...@@ -37,22 +46,94 @@ class _PoemVideoPlayerState extends State<PoemVideoPlayer> { ...@@ -37,22 +46,94 @@ class _PoemVideoPlayerState extends State<PoemVideoPlayer> {
37 alignment: Alignment.center, 46 alignment: Alignment.center,
38 child: Text( 47 child: Text(
39 widget.title ?? "视频播放", 48 widget.title ?? "视频播放",
40 - style: const TextStyle(color: Colors.white), 49 + style: const TextStyle(
50 + color: Colors.white,
51 + ),
41 ), 52 ),
42 ), 53 ),
43 ), 54 ),
44 - body: Container( 55 + body: Stack(
45 - alignment: Alignment.center, 56 + children: [
46 - child: FijkView( 57 + FijkView(
47 - height: MediaQuery.of(context).size.height, 58 + height: MediaQuery.of(context).size.height,
48 - player: player, 59 + player: player,
49 - ), 60 + fit: FijkFit.fill,
61 + ),
62 + Padding(
63 + padding: EdgeInsets.fromLTRB(10.px, 30.px, 10.px, 10.px),
64 + child: Column(
65 + crossAxisAlignment: CrossAxisAlignment.start,
66 + children: [
67 + Text(
68 + "题破山寺后禅院",
69 + style: TextStyle(
70 + color: Colors.white,
71 + fontSize: 28.px,
72 + ),
73 + ),
74 + Gaps.vGap10,
75 + Text(
76 + "常建",
77 + style: TextStyle(
78 + color: Colors.white,
79 + fontSize: 15.px,
80 + ),
81 + ),
82 + Gaps.vGap5,
83 + Text(
84 + "清晨入古寺,\n初日照高林。\n曲径通幽处,\n禅房花木深。\n山光悦鸟性,\n潭影空人心。\n万籁此都寂,\n但余钟磬音。\n",
85 + style: TextStyle(
86 + color: Colors.white,
87 + fontFamily: "ZCOOLXiaoWei",
88 + fontSize: 25.px,
89 + ),
90 + ),
91 + Gaps.vGap5,
92 + Text(
93 + "临者:老魔取西经",
94 + style: TextStyle(
95 + color: Colors.white,
96 + fontSize: 15.px,
97 + ),
98 + ),
99 + Text(
100 + "2022年01月25日 辰时三刻",
101 + style: TextStyle(
102 + color: Colors.white,
103 + fontSize: 15.px,
104 + ),
105 + ),
106 + ],
107 + ),
108 + ),
109 + Positioned(
110 + bottom: 10.px,
111 + right: 20.px,
112 + child: ElevatedButton(
113 + onPressed: () {
114 + NavigatorUtils.push(
115 + context,
116 + '${PoemRouter.poemPublish}?data=100',
117 + clearStack: true
118 + );
119 + },
120 + child: Text(
121 + "下一步",
122 + style: TextStyle(fontSize: 15.px),
123 + ),
124 + style: TextButton.styleFrom(
125 + primary: Colors.white,
126 + backgroundColor: Colors.black54,
127 + ),
128 + ),
129 + ),
130 + ],
50 )); 131 ));
51 } 132 }
52 133
53 @override 134 @override
54 void dispose() { 135 void dispose() {
55 - super.dispose();
56 player.release(); 136 player.release();
137 + super.dispose();
57 } 138 }
58 } 139 }
......