Showing
8 changed files
with
504 additions
and
7 deletions
lib/common/permission_request_widget.dart
0 → 100644
1 | +import 'dart:io'; | ||
2 | + | ||
3 | +import 'package:flutter/material.dart'; | ||
4 | +import 'package:flutter/services.dart'; | ||
5 | +import 'package:permission_handler/permission_handler.dart'; | ||
6 | + | ||
7 | +/// 创建人: Created by zhaolong | ||
8 | +/// 创建时间:Created by on 2020/12/9. | ||
9 | +/// | ||
10 | +/// 可关注公众号:我的大前端生涯 获取最新技术分享 | ||
11 | +/// 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm | ||
12 | +/// 可关注博客:https://blog.csdn.net/zl18603543572 | ||
13 | +/// | ||
14 | +/// 代码清单 | ||
15 | +///权限请求模版 | ||
16 | +class PermissionRequestWidget extends StatefulWidget { | ||
17 | + final Permission permission; | ||
18 | + final List<String> permissionList; | ||
19 | + final bool isCloseApp; | ||
20 | + final String leftButtonText; | ||
21 | + | ||
22 | + const PermissionRequestWidget({ | ||
23 | + Key? key, | ||
24 | + required this.permission, | ||
25 | + required this.permissionList, | ||
26 | + this.leftButtonText = "再考虑一下", | ||
27 | + this.isCloseApp = false, | ||
28 | + }) : super(key: key); | ||
29 | + | ||
30 | + @override | ||
31 | + _PermissionRequestWidgetState createState() => | ||
32 | + _PermissionRequestWidgetState(); | ||
33 | +} | ||
34 | + | ||
35 | +class _PermissionRequestWidgetState extends State<PermissionRequestWidget> | ||
36 | + with WidgetsBindingObserver { | ||
37 | + //页面的初始化函数 | ||
38 | + @override | ||
39 | + void initState() { | ||
40 | + super.initState(); | ||
41 | + checkPermission(); | ||
42 | + //注册观察者 | ||
43 | + if (WidgetsBinding.instance != null) { | ||
44 | + WidgetsBinding.instance!.addObserver(this); | ||
45 | + } | ||
46 | + } | ||
47 | + | ||
48 | + @override | ||
49 | + void didChangeAppLifecycleState(AppLifecycleState state) { | ||
50 | + super.didChangeAppLifecycleState(state); | ||
51 | + if (state == AppLifecycleState.resumed && _isGoSetting) { | ||
52 | + checkPermission(); | ||
53 | + } | ||
54 | + } | ||
55 | + | ||
56 | + ///[PermissionStatus.denied] 用户拒绝访问所请求的特性 | ||
57 | + ///[PermissionStatus.granted] 用户被授予对所请求特性的访问权。 | ||
58 | + ///[PermissionStatus.restricted] iOS 平台 用户拒绝这个权限 | ||
59 | + ///[PermissionStatus.limited] 用户已授权此应用程序进行有限访问。 | ||
60 | + ///[PermissionStatus.permanentlyDenied] 被永久拒绝 | ||
61 | + void checkPermission({PermissionStatus? status}) async { | ||
62 | + //权限 | ||
63 | + Permission permission = widget.permission; | ||
64 | + | ||
65 | + status ??= await permission.status; | ||
66 | + if (status.isGranted) { | ||
67 | + Navigator.of(context).pop(true); | ||
68 | + return; | ||
69 | + } | ||
70 | + if (!status.isLimited) { | ||
71 | + //第一次申请 | ||
72 | + showPermissionAlert(widget.permissionList[0], "同意", permission); | ||
73 | + } else if (status.isDenied) { | ||
74 | + if (Platform.isIOS) { | ||
75 | + showPermissionAlert(widget.permissionList[2], "去设置中心", permission, | ||
76 | + isSetting: true); | ||
77 | + return; | ||
78 | + } | ||
79 | + //用户第一次申请拒绝 | ||
80 | + showPermissionAlert(widget.permissionList[1], "重试", permission); | ||
81 | + } else if (status.isPermanentlyDenied) { | ||
82 | + //第二次申请 用户拒绝 | ||
83 | + showPermissionAlert(widget.permissionList[2], "去设置中心", permission, | ||
84 | + isSetting: true); | ||
85 | + } else { | ||
86 | + //通过 | ||
87 | + Navigator.of(context).pop(true); | ||
88 | + } | ||
89 | + } | ||
90 | + | ||
91 | + //是否去设置中心 | ||
92 | + bool _isGoSetting = false; | ||
93 | + | ||
94 | + void showPermissionAlert( | ||
95 | + String message, | ||
96 | + String rightString, | ||
97 | + Permission permission, { | ||
98 | + bool isSetting = false, | ||
99 | + }) { | ||
100 | + showDialog( | ||
101 | + builder: (BuildContext context) { | ||
102 | + return AlertDialog( | ||
103 | + title: const Text("温馨提示"), | ||
104 | + content: Container( | ||
105 | + padding: const EdgeInsets.all(12), | ||
106 | + child: Text(message), | ||
107 | + ), | ||
108 | + actions: [ | ||
109 | + //左边的按钮 | ||
110 | + TextButton( | ||
111 | + child: Text(widget.leftButtonText), | ||
112 | + onPressed: () { | ||
113 | + if (widget.isCloseApp) { | ||
114 | + closeApp(); | ||
115 | + } else { | ||
116 | + Navigator.of(context).pop(false); | ||
117 | + } | ||
118 | + }, | ||
119 | + ), | ||
120 | + //右边的按钮 | ||
121 | + TextButton( | ||
122 | + child: Text(rightString), | ||
123 | + onPressed: () { | ||
124 | + //关闭弹框 | ||
125 | + Navigator.of(context).pop(); | ||
126 | + if (isSetting) { | ||
127 | + _isGoSetting = true; | ||
128 | + //去设置中心 | ||
129 | + openAppSettings(); | ||
130 | + } else { | ||
131 | + //申请权限 | ||
132 | + requestPermission(permission); | ||
133 | + } | ||
134 | + }, | ||
135 | + ) | ||
136 | + ], | ||
137 | + ); | ||
138 | + }, | ||
139 | + context: context); | ||
140 | + } | ||
141 | + | ||
142 | + void requestPermission(Permission permission) async { | ||
143 | + //发起权限申请 | ||
144 | + PermissionStatus status = await permission.request(); | ||
145 | + //校验 | ||
146 | + checkPermission(); | ||
147 | + } | ||
148 | + | ||
149 | + /// TODO 暂未使用 | ||
150 | + void requestPermissionList(List<Permission> list) async { | ||
151 | + //多个权限申请 | ||
152 | + Map<Permission, PermissionStatus> statuses = await [ | ||
153 | + Permission.location, | ||
154 | + Permission.storage, | ||
155 | + ].request(); | ||
156 | + } | ||
157 | + | ||
158 | + void closeApp() { | ||
159 | + //关闭应用的方法 | ||
160 | + SystemChannels.platform.invokeMethod("SystemNavigator.pop"); | ||
161 | + } | ||
162 | + | ||
163 | + @override | ||
164 | + void dispose() { | ||
165 | + //注销观察者 | ||
166 | + if (WidgetsBinding.instance != null) { | ||
167 | + WidgetsBinding.instance!.removeObserver(this); | ||
168 | + } | ||
169 | + | ||
170 | + super.dispose(); | ||
171 | + } | ||
172 | + | ||
173 | + @override | ||
174 | + Widget build(BuildContext context) { | ||
175 | + return const Scaffold( | ||
176 | + backgroundColor: Colors.transparent, | ||
177 | + ); | ||
178 | + } | ||
179 | +} |
lib/common/protocol_model.dart
0 → 100644
1 | +import 'package:flutter/gestures.dart'; | ||
2 | +import 'package:flutter/material.dart'; | ||
3 | +import 'package:one_poem/res/constant.dart'; | ||
4 | +import 'package:one_poem/routers/fluro_navigator.dart'; | ||
5 | + | ||
6 | +/// 创建人: Created by zhaolong | ||
7 | +/// 创建时间:Created by on 2020/12/12. | ||
8 | +/// | ||
9 | +/// 可关注公众号:我的大前端生涯 获取最新技术分享 | ||
10 | +/// 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm | ||
11 | +/// 可关注博客:https://blog.csdn.net/zl18603543572 | ||
12 | +/// | ||
13 | +/// 代码清单 | ||
14 | +///代码清单 | ||
15 | +class ProtocolModel { | ||
16 | + late TapGestureRecognizer _registerProtocolRecognizer; | ||
17 | + late TapGestureRecognizer _privacyProtocolRecognizer; | ||
18 | + | ||
19 | + ///用来显示 用户协议对话框 | ||
20 | + Future<bool> showProtocolFunction(BuildContext context) async { | ||
21 | + //注册协议的手势 | ||
22 | + _registerProtocolRecognizer = TapGestureRecognizer(); | ||
23 | + //隐私协议的手势 | ||
24 | + _privacyProtocolRecognizer = TapGestureRecognizer(); | ||
25 | + | ||
26 | + //苹果风格弹框 | ||
27 | + bool isShow = await showDialog( | ||
28 | + //上下文对象 | ||
29 | + context: context, | ||
30 | + //对话框内容 | ||
31 | + builder: (BuildContext context) { | ||
32 | + return showAlertDialog(context); | ||
33 | + }, | ||
34 | + ); | ||
35 | + | ||
36 | + ///销毁 | ||
37 | + _registerProtocolRecognizer.dispose(); | ||
38 | + _privacyProtocolRecognizer.dispose(); | ||
39 | + | ||
40 | + return Future.value(isShow); | ||
41 | + } | ||
42 | + | ||
43 | + AlertDialog showAlertDialog(BuildContext context) { | ||
44 | + return AlertDialog( | ||
45 | + title: const Text("温馨提示"), | ||
46 | + content: Container( | ||
47 | + height: 260, | ||
48 | + padding: const EdgeInsets.all(1), | ||
49 | + //可滑动布局 | ||
50 | + child: SingleChildScrollView( | ||
51 | + child: buildContent(context), | ||
52 | + ), | ||
53 | + ), | ||
54 | + actions: [ | ||
55 | + TextButton( | ||
56 | + child: const Text("不同意"), | ||
57 | + onPressed: () { | ||
58 | + Navigator.of(context).pop(false); | ||
59 | + }, | ||
60 | + ), | ||
61 | + TextButton( | ||
62 | + child: const Text("同意"), | ||
63 | + onPressed: () { | ||
64 | + Navigator.of(context).pop(true); | ||
65 | + }, | ||
66 | + ), | ||
67 | + ], | ||
68 | + ); | ||
69 | + } | ||
70 | + | ||
71 | + //协议说明文案 | ||
72 | + String userPrivateProtocol = | ||
73 | + "我们一向尊重并会严格保护用户在使用本产品时的合法权益(包括用户隐私、用户数据等)不受到任何侵犯。本协议(包括本文最后部分的隐私政策)是用户(包括通过各种合法途径获取到本产品的自然人、法人或其他组织机构,以下简称“用户”或“您”)与我们之间针对本产品相关事项最终的、完整的且排他的协议,并取代、合并之前的当事人之间关于上述事项的讨论和协议。本协议将对用户使用本产品的行为产生法律约束力,您已承诺和保证有权利和能力订立本协议。用户开始使用本产品将视为已经接受本协议,请认真阅读并理解本协议中各种条款,包括免除和限制我们的免责条款和对用户的权利限制(未成年人审阅时应由法定监护人陪同),如果您不能接受本协议中的全部条款,请勿开始使用本产品"; | ||
74 | + | ||
75 | + buildContent(BuildContext context) { | ||
76 | + return RichText( | ||
77 | + text: TextSpan( | ||
78 | + text: "请您在使用本产品之前仔细阅读", | ||
79 | + style: TextStyle(color: Colors.grey[600]), | ||
80 | + children: [ | ||
81 | + TextSpan( | ||
82 | + text: "《用户协议》", | ||
83 | + style: const TextStyle(color: Colors.blue), | ||
84 | + //点击事件 | ||
85 | + recognizer: _registerProtocolRecognizer | ||
86 | + ..onTap = () { | ||
87 | + //打开用户协议 | ||
88 | + openUserProtocol(context); | ||
89 | + }, | ||
90 | + ), | ||
91 | + TextSpan( | ||
92 | + text: "与", | ||
93 | + style: TextStyle(color: Colors.grey[600]), | ||
94 | + ), | ||
95 | + TextSpan( | ||
96 | + text: "《隐私协议》", | ||
97 | + style: const TextStyle(color: Colors.blue), | ||
98 | + //点击事件 | ||
99 | + recognizer: _privacyProtocolRecognizer | ||
100 | + ..onTap = () { | ||
101 | + //打开隐私协议 | ||
102 | + openPrivateProtocol(context); | ||
103 | + }, | ||
104 | + ), | ||
105 | + TextSpan( | ||
106 | + text: userPrivateProtocol, | ||
107 | + style: TextStyle(color: Colors.grey[600]), | ||
108 | + ), | ||
109 | + ]), | ||
110 | + ); | ||
111 | + } | ||
112 | + | ||
113 | + //查看用户协议 | ||
114 | + void openUserProtocol(BuildContext context) { | ||
115 | + NavigatorUtils.goWebViewPage( | ||
116 | + context, | ||
117 | + '用户协议', | ||
118 | + Constant.protocolUrl, | ||
119 | + ); | ||
120 | + } | ||
121 | + | ||
122 | + //查看隐私协议 | ||
123 | + void openPrivateProtocol(BuildContext context) { | ||
124 | + NavigatorUtils.goWebViewPage( | ||
125 | + context, | ||
126 | + '隐私协议', | ||
127 | + Constant.privacyUrl, | ||
128 | + ); | ||
129 | + } | ||
130 | +} |
1 | import 'package:flustars/flustars.dart'; | 1 | import 'package:flustars/flustars.dart'; |
2 | import 'package:flutter/foundation.dart'; | 2 | import 'package:flutter/foundation.dart'; |
3 | +import 'package:flutter/gestures.dart'; | ||
3 | import 'package:flutter/material.dart'; | 4 | import 'package:flutter/material.dart'; |
4 | import 'package:flutter/services.dart'; | 5 | import 'package:flutter/services.dart'; |
6 | +import 'package:one_poem/common/permission_request_widget.dart'; | ||
7 | +import 'package:one_poem/common/protocol_model.dart'; | ||
8 | +import 'package:one_poem/home/webview_page.dart'; | ||
5 | import 'package:one_poem/login/widgets/my_text_field.dart'; | 9 | import 'package:one_poem/login/widgets/my_text_field.dart'; |
6 | import 'package:one_poem/res/constant.dart'; | 10 | import 'package:one_poem/res/constant.dart'; |
7 | import 'package:one_poem/res/resources.dart'; | 11 | import 'package:one_poem/res/resources.dart'; |
... | @@ -18,6 +22,8 @@ import '../login_router.dart'; | ... | @@ -18,6 +22,8 @@ import '../login_router.dart'; |
18 | import 'package:flutter_gen/gen_l10n/one_poem_localizations.dart'; | 22 | import 'package:flutter_gen/gen_l10n/one_poem_localizations.dart'; |
19 | import 'package:one_poem/extension/int_extension.dart'; | 23 | import 'package:one_poem/extension/int_extension.dart'; |
20 | 24 | ||
25 | +import 'package:permission_handler/permission_handler.dart'; | ||
26 | + | ||
21 | /// design/1注册登录/index.html | 27 | /// design/1注册登录/index.html |
22 | class LoginPage extends StatefulWidget { | 28 | class LoginPage extends StatefulWidget { |
23 | const LoginPage({Key? key}) : super(key: key); | 29 | const LoginPage({Key? key}) : super(key: key); |
... | @@ -27,7 +33,7 @@ class LoginPage extends StatefulWidget { | ... | @@ -27,7 +33,7 @@ class LoginPage extends StatefulWidget { |
27 | } | 33 | } |
28 | 34 | ||
29 | class _LoginPageState extends State<LoginPage> | 35 | class _LoginPageState extends State<LoginPage> |
30 | - with ChangeNotifierMixin<LoginPage> { | 36 | + with ChangeNotifierMixin<LoginPage>, ProtocolModel { |
31 | //定义一个controller | 37 | //定义一个controller |
32 | final TextEditingController _nameController = TextEditingController(); | 38 | final TextEditingController _nameController = TextEditingController(); |
33 | final TextEditingController _passwordController = TextEditingController(); | 39 | final TextEditingController _passwordController = TextEditingController(); |
... | @@ -55,6 +61,40 @@ class _LoginPageState extends State<LoginPage> | ... | @@ -55,6 +61,40 @@ class _LoginPageState extends State<LoginPage> |
55 | overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]); | 61 | overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]); |
56 | }); | 62 | }); |
57 | _nameController.text = SpUtil.getString(Constant.phone).nullSafe; | 63 | _nameController.text = SpUtil.getString(Constant.phone).nullSafe; |
64 | + | ||
65 | + List<String> _list = [ | ||
66 | + "为您更好的体验应用,所以需要获取您的手机文件存储权限,以保存您的一些偏好设置", | ||
67 | + "您已拒绝权限,所以无法保存您的一些偏好设置,将无法使用APP", | ||
68 | + "您已拒绝权限,请在设置中心中同意APP的权限请求", | ||
69 | + "其他错误" | ||
70 | + ]; | ||
71 | + | ||
72 | + Future.delayed(Duration.zero, () { | ||
73 | + NavigatorUtils.pushPageByFade( | ||
74 | + context: context, | ||
75 | + //目标页面 | ||
76 | + targetPage: PermissionRequestWidget( | ||
77 | + //所需要申请的权限 | ||
78 | + permission: Permission.camera, | ||
79 | + //显示关闭应用按钮 | ||
80 | + isCloseApp: true, | ||
81 | + //提示文案 | ||
82 | + permissionList: _list, | ||
83 | + ), | ||
84 | + //权限申请结果 | ||
85 | + dismissCallBack: (value) { | ||
86 | + showPrivacyPage(); | ||
87 | + }); | ||
88 | + }); | ||
89 | + } | ||
90 | + | ||
91 | + void showPrivacyPage() async { | ||
92 | + bool isAgreement = await showProtocolFunction(context); | ||
93 | + if (isAgreement) { | ||
94 | + // next(); | ||
95 | + } else { | ||
96 | + SystemChannels.platform.invokeMethod("SystemNavigator.pop"); | ||
97 | + } | ||
58 | } | 98 | } |
59 | 99 | ||
60 | void _verify() { | 100 | void _verify() { |
... | @@ -125,6 +165,46 @@ class _LoginPageState extends State<LoginPage> | ... | @@ -125,6 +165,46 @@ class _LoginPageState extends State<LoginPage> |
125 | hintText: OnePoemLocalizations.of(context).inputPasswordHint, | 165 | hintText: OnePoemLocalizations.of(context).inputPasswordHint, |
126 | ), | 166 | ), |
127 | Gaps.vGap24, | 167 | Gaps.vGap24, |
168 | + Text.rich( | ||
169 | + TextSpan( | ||
170 | + text: '登录即代表同意并阅读', | ||
171 | + style: const TextStyle(fontSize: 12, color: Color(0xFF999999)), | ||
172 | + children: [ | ||
173 | + TextSpan( | ||
174 | + text: '《用户协议》', | ||
175 | + style: TextStyle(color: Theme.of(context).primaryColor), | ||
176 | + recognizer: TapGestureRecognizer() | ||
177 | + ..onTap = () { | ||
178 | + Navigator.of(context) | ||
179 | + .push(MaterialPageRoute(builder: (context) { | ||
180 | + return const WebViewPage( | ||
181 | + title: '《用户协议》', | ||
182 | + url: Constant.protocolUrl, | ||
183 | + ); | ||
184 | + })); | ||
185 | + }, | ||
186 | + ), | ||
187 | + const TextSpan(text: '和'), | ||
188 | + TextSpan( | ||
189 | + text: '《隐私政策》', | ||
190 | + style: TextStyle(color: Theme.of(context).primaryColor), | ||
191 | + recognizer: TapGestureRecognizer() | ||
192 | + ..onTap = () { | ||
193 | + Navigator.of(context).push( | ||
194 | + MaterialPageRoute( | ||
195 | + builder: (context) { | ||
196 | + return const WebViewPage( | ||
197 | + title: '《隐私政策》', | ||
198 | + url: Constant.privacyUrl, | ||
199 | + ); | ||
200 | + }, | ||
201 | + ), | ||
202 | + ); | ||
203 | + }, | ||
204 | + ), | ||
205 | + ]), | ||
206 | + ), | ||
207 | + Gaps.vGap16, | ||
128 | MyButton( | 208 | MyButton( |
129 | key: const Key('login'), | 209 | key: const Key('login'), |
130 | onPressed: _clickable ? _login : null, | 210 | onPressed: _clickable ? _login : null, | ... | ... |
1 | import 'package:flutter/foundation.dart'; | 1 | import 'package:flutter/foundation.dart'; |
2 | +import 'package:flutter/gestures.dart'; | ||
2 | import 'package:flutter/material.dart'; | 3 | import 'package:flutter/material.dart'; |
3 | import 'package:flutter/services.dart'; | 4 | import 'package:flutter/services.dart'; |
5 | +import 'package:one_poem/home/webview_page.dart'; | ||
4 | import 'package:one_poem/login/widgets/my_text_field.dart'; | 6 | import 'package:one_poem/login/widgets/my_text_field.dart'; |
5 | import 'package:one_poem/res/resources.dart'; | 7 | import 'package:one_poem/res/resources.dart'; |
6 | import 'package:one_poem/res/styles.dart'; | 8 | import 'package:one_poem/res/styles.dart'; |
... | @@ -32,6 +34,7 @@ class _RegisterPageState extends State<RegisterPage> | ... | @@ -32,6 +34,7 @@ class _RegisterPageState extends State<RegisterPage> |
32 | final FocusNode _nodeText2 = FocusNode(); | 34 | final FocusNode _nodeText2 = FocusNode(); |
33 | final FocusNode _nodeText3 = FocusNode(); | 35 | final FocusNode _nodeText3 = FocusNode(); |
34 | bool _clickable = false; | 36 | bool _clickable = false; |
37 | + bool _switchSelected=true; | ||
35 | 38 | ||
36 | @override | 39 | @override |
37 | Map<ChangeNotifier, List<VoidCallback>?>? changeNotifier() { | 40 | Map<ChangeNotifier, List<VoidCallback>?>? changeNotifier() { |
... | @@ -130,6 +133,39 @@ class _RegisterPageState extends State<RegisterPage> | ... | @@ -130,6 +133,39 @@ class _RegisterPageState extends State<RegisterPage> |
130 | keyboardType: TextInputType.visiblePassword, | 133 | keyboardType: TextInputType.visiblePassword, |
131 | hintText: OnePoemLocalizations.of(context).inputPasswordHint, | 134 | hintText: OnePoemLocalizations.of(context).inputPasswordHint, |
132 | ), | 135 | ), |
136 | + Gaps.vGap8, | ||
137 | + Text.rich( | ||
138 | + TextSpan( | ||
139 | + text: '登录即代表同意并阅读', | ||
140 | + style: TextStyle(fontSize: 14, color: const Color(0xFF999999)), | ||
141 | + children: [ | ||
142 | + TextSpan( | ||
143 | + text: '《用户协议》', | ||
144 | + style: TextStyle(color: Theme.of(context).primaryColor), | ||
145 | + recognizer: TapGestureRecognizer() | ||
146 | + ..onTap = () { | ||
147 | + Navigator.of(context) | ||
148 | + .push(MaterialPageRoute(builder: (context) { | ||
149 | + return WebViewPage( | ||
150 | + title: '《用户协议》', url: 'https://flutter.dev'); | ||
151 | + })); | ||
152 | + }, | ||
153 | + ), | ||
154 | + TextSpan(text: '和'), | ||
155 | + TextSpan( | ||
156 | + text: '《隐私政策》', | ||
157 | + style: TextStyle(color: Theme.of(context).primaryColor), | ||
158 | + recognizer: TapGestureRecognizer() | ||
159 | + ..onTap = () { | ||
160 | + Navigator.of(context) | ||
161 | + .push(MaterialPageRoute(builder: (context) { | ||
162 | + return WebViewPage( | ||
163 | + title: '《隐私政策》', url: 'https://flutter.dev'); | ||
164 | + })); | ||
165 | + }, | ||
166 | + ), | ||
167 | + ]), | ||
168 | + ), | ||
133 | Gaps.vGap24, | 169 | Gaps.vGap24, |
134 | MyButton( | 170 | MyButton( |
135 | key: const Key('register'), | 171 | key: const Key('register'), | ... | ... |
... | @@ -2,6 +2,9 @@ import 'package:flutter/foundation.dart'; | ... | @@ -2,6 +2,9 @@ import 'package:flutter/foundation.dart'; |
2 | 2 | ||
3 | class Constant { | 3 | class Constant { |
4 | 4 | ||
5 | + static const String privacyUrl = "https://www.mofunenglish.com/index.php?act=about&mdl=agreement"; | ||
6 | + static const String protocolUrl = "https://www.mofunenglish.com/index.php?act=about&mdl=agreement"; | ||
7 | + | ||
5 | /// App运行在Release环境时,inProduction为true;当App运行在Debug和Profile环境时,inProduction为false | 8 | /// App运行在Release环境时,inProduction为true;当App运行在Debug和Profile环境时,inProduction为false |
6 | static const bool inProduction = kReleaseMode; | 9 | static const bool inProduction = kReleaseMode; |
7 | 10 | ... | ... |
... | @@ -5,11 +5,12 @@ import 'routers.dart'; | ... | @@ -5,11 +5,12 @@ import 'routers.dart'; |
5 | 5 | ||
6 | /// fluro的路由跳转工具类 | 6 | /// fluro的路由跳转工具类 |
7 | class NavigatorUtils { | 7 | class NavigatorUtils { |
8 | - | ||
9 | static void push(BuildContext context, String path, | 8 | static void push(BuildContext context, String path, |
10 | {bool replace = false, bool clearStack = false, Object? arguments}) { | 9 | {bool replace = false, bool clearStack = false, Object? arguments}) { |
11 | unfocus(); | 10 | unfocus(); |
12 | - Routes.router.navigateTo(context, path, | 11 | + Routes.router.navigateTo( |
12 | + context, | ||
13 | + path, | ||
13 | replace: replace, | 14 | replace: replace, |
14 | clearStack: clearStack, | 15 | clearStack: clearStack, |
15 | transition: TransitionType.native, | 16 | transition: TransitionType.native, |
... | @@ -19,17 +20,22 @@ class NavigatorUtils { | ... | @@ -19,17 +20,22 @@ class NavigatorUtils { |
19 | ); | 20 | ); |
20 | } | 21 | } |
21 | 22 | ||
22 | - static void pushResult(BuildContext context, String path, Function(Object) function, | 23 | + static void pushResult( |
24 | + BuildContext context, String path, Function(Object) function, | ||
23 | {bool replace = false, bool clearStack = false, Object? arguments}) { | 25 | {bool replace = false, bool clearStack = false, Object? arguments}) { |
24 | unfocus(); | 26 | unfocus(); |
25 | - Routes.router.navigateTo(context, path, | 27 | + Routes.router |
28 | + .navigateTo( | ||
29 | + context, | ||
30 | + path, | ||
26 | replace: replace, | 31 | replace: replace, |
27 | clearStack: clearStack, | 32 | clearStack: clearStack, |
28 | transition: TransitionType.native, | 33 | transition: TransitionType.native, |
29 | routeSettings: RouteSettings( | 34 | routeSettings: RouteSettings( |
30 | arguments: arguments, | 35 | arguments: arguments, |
31 | ), | 36 | ), |
32 | - ).then((Object? result) { | 37 | + ) |
38 | + .then((Object? result) { | ||
33 | // 页面返回result为null | 39 | // 页面返回result为null |
34 | if (result == null) { | 40 | if (result == null) { |
35 | return; | 41 | return; |
... | @@ -55,7 +61,8 @@ class NavigatorUtils { | ... | @@ -55,7 +61,8 @@ class NavigatorUtils { |
55 | /// 跳到WebView页 | 61 | /// 跳到WebView页 |
56 | static void goWebViewPage(BuildContext context, String title, String url) { | 62 | static void goWebViewPage(BuildContext context, String title, String url) { |
57 | //fluro 不支持传中文,需转换 | 63 | //fluro 不支持传中文,需转换 |
58 | - push(context, '${Routes.webViewPage}?title=${Uri.encodeComponent(title)}&url=${Uri.encodeComponent(url)}'); | 64 | + push(context, |
65 | + '${Routes.webViewPage}?title=${Uri.encodeComponent(title)}&url=${Uri.encodeComponent(url)}'); | ||
59 | } | 66 | } |
60 | 67 | ||
61 | static void unfocus() { | 68 | static void unfocus() { |
... | @@ -64,4 +71,50 @@ class NavigatorUtils { | ... | @@ -64,4 +71,50 @@ class NavigatorUtils { |
64 | // https://github.com/flutter/flutter/issues/47128#issuecomment-627551073 | 71 | // https://github.com/flutter/flutter/issues/47128#issuecomment-627551073 |
65 | FocusManager.instance.primaryFocus?.unfocus(); | 72 | FocusManager.instance.primaryFocus?.unfocus(); |
66 | } | 73 | } |
74 | + | ||
75 | + ///普通打开页面的方法 | ||
76 | + ///[context] 上下文对象 | ||
77 | + ///[targetPage] 目标页面 | ||
78 | + ///[isReplace] 是否替换当前页面 A -B | ||
79 | + ///[opaque] 是否以背景透明的方式打开页面 | ||
80 | + static void pushPageByFade({ | ||
81 | + required BuildContext context, | ||
82 | + required Widget targetPage, | ||
83 | + bool isReplace = false, | ||
84 | + int startMills = 400, | ||
85 | + bool opaque = false, | ||
86 | + Function(dynamic value)? dismissCallBack, | ||
87 | + }) { | ||
88 | + PageRoute pageRoute = PageRouteBuilder( | ||
89 | + //背景透明 方式打开新的页面 | ||
90 | + opaque: opaque, | ||
91 | + pageBuilder: (BuildContext context, Animation<double> animation, | ||
92 | + Animation<double> secondaryAnimation) { | ||
93 | + return targetPage; | ||
94 | + }, | ||
95 | + transitionDuration: Duration(milliseconds: startMills), | ||
96 | + //动画 | ||
97 | + transitionsBuilder: (BuildContext context, Animation<double> animation, | ||
98 | + Animation<double> secondaryAnimation, Widget child) { | ||
99 | + return FadeTransition( | ||
100 | + opacity: animation, | ||
101 | + child: child, | ||
102 | + ); | ||
103 | + }, | ||
104 | + ); | ||
105 | + | ||
106 | + if (isReplace) { | ||
107 | + Navigator.of(context).pushReplacement(pageRoute).then((value) { | ||
108 | + if (dismissCallBack != null) { | ||
109 | + dismissCallBack(value); | ||
110 | + } | ||
111 | + }); | ||
112 | + } else { | ||
113 | + Navigator.of(context).push(pageRoute).then((value) { | ||
114 | + if (dismissCallBack != null) { | ||
115 | + dismissCallBack(value); | ||
116 | + } | ||
117 | + }); | ||
118 | + } | ||
119 | + } | ||
67 | } | 120 | } | ... | ... |
... | @@ -708,6 +708,20 @@ packages: | ... | @@ -708,6 +708,20 @@ packages: |
708 | url: "https://pub.dartlang.org" | 708 | url: "https://pub.dartlang.org" |
709 | source: hosted | 709 | source: hosted |
710 | version: "1.11.1" | 710 | version: "1.11.1" |
711 | + permission_handler: | ||
712 | + dependency: "direct dev" | ||
713 | + description: | ||
714 | + name: permission_handler | ||
715 | + url: "https://pub.dartlang.org" | ||
716 | + source: hosted | ||
717 | + version: "8.3.0" | ||
718 | + permission_handler_platform_interface: | ||
719 | + dependency: transitive | ||
720 | + description: | ||
721 | + name: permission_handler_platform_interface | ||
722 | + url: "https://pub.dartlang.org" | ||
723 | + source: hosted | ||
724 | + version: "3.7.0" | ||
711 | petitparser: | 725 | petitparser: |
712 | dependency: transitive | 726 | dependency: transitive |
713 | description: | 727 | description: | ... | ... |
... | @@ -129,6 +129,8 @@ dev_dependencies: | ... | @@ -129,6 +129,8 @@ dev_dependencies: |
129 | flutter_launcher_icons: ^0.9.2 | 129 | flutter_launcher_icons: ^0.9.2 |
130 | flutter_native_splash: ^1.3.2 | 130 | flutter_native_splash: ^1.3.2 |
131 | 131 | ||
132 | + permission_handler: ^8.3.0 | ||
133 | + | ||
132 | # For information on the generic Dart part of this file, see the | 134 | # For information on the generic Dart part of this file, see the |
133 | # following page: https://dart.dev/tools/pub/pubspec | 135 | # following page: https://dart.dev/tools/pub/pubspec |
134 | 136 | ... | ... |
-
Please register or login to post a comment