Toggle navigation
Toggle navigation
This project
Loading...
Sign in
OnePoem
/
OnePoem-App
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
Reason Pun
2022-01-11 23:54:11 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
01d62a44877de8c567ddce850a2674ecde52d4e8
01d62a44
1 parent
02110031
增加了权限申请页面和隐私提示页面
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
505 additions
and
8 deletions
lib/common/permission_request_widget.dart
lib/common/protocol_model.dart
lib/login/page/login_page.dart
lib/login/page/register_page.dart
lib/res/constant.dart
lib/routers/fluro_navigator.dart
pubspec.lock
pubspec.yaml
lib/common/permission_request_widget.dart
0 → 100644
View file @
01d62a4
import
'dart:io'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:permission_handler/permission_handler.dart'
;
/// 创建人: Created by zhaolong
/// 创建时间:Created by on 2020/12/9.
///
/// 可关注公众号:我的大前端生涯 获取最新技术分享
/// 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm
/// 可关注博客:https://blog.csdn.net/zl18603543572
///
/// 代码清单
///权限请求模版
class
PermissionRequestWidget
extends
StatefulWidget
{
final
Permission
permission
;
final
List
<
String
>
permissionList
;
final
bool
isCloseApp
;
final
String
leftButtonText
;
const
PermissionRequestWidget
({
Key
?
key
,
required
this
.
permission
,
required
this
.
permissionList
,
this
.
leftButtonText
=
"再考虑一下"
,
this
.
isCloseApp
=
false
,
})
:
super
(
key:
key
);
@override
_PermissionRequestWidgetState
createState
()
=>
_PermissionRequestWidgetState
();
}
class
_PermissionRequestWidgetState
extends
State
<
PermissionRequestWidget
>
with
WidgetsBindingObserver
{
//页面的初始化函数
@override
void
initState
()
{
super
.
initState
();
checkPermission
();
//注册观察者
if
(
WidgetsBinding
.
instance
!=
null
)
{
WidgetsBinding
.
instance
!.
addObserver
(
this
);
}
}
@override
void
didChangeAppLifecycleState
(
AppLifecycleState
state
)
{
super
.
didChangeAppLifecycleState
(
state
);
if
(
state
==
AppLifecycleState
.
resumed
&&
_isGoSetting
)
{
checkPermission
();
}
}
///[PermissionStatus.denied] 用户拒绝访问所请求的特性
///[PermissionStatus.granted] 用户被授予对所请求特性的访问权。
///[PermissionStatus.restricted] iOS 平台 用户拒绝这个权限
///[PermissionStatus.limited] 用户已授权此应用程序进行有限访问。
///[PermissionStatus.permanentlyDenied] 被永久拒绝
void
checkPermission
({
PermissionStatus
?
status
})
async
{
//权限
Permission
permission
=
widget
.
permission
;
status
??=
await
permission
.
status
;
if
(
status
.
isGranted
)
{
Navigator
.
of
(
context
).
pop
(
true
);
return
;
}
if
(!
status
.
isLimited
)
{
//第一次申请
showPermissionAlert
(
widget
.
permissionList
[
0
],
"同意"
,
permission
);
}
else
if
(
status
.
isDenied
)
{
if
(
Platform
.
isIOS
)
{
showPermissionAlert
(
widget
.
permissionList
[
2
],
"去设置中心"
,
permission
,
isSetting:
true
);
return
;
}
//用户第一次申请拒绝
showPermissionAlert
(
widget
.
permissionList
[
1
],
"重试"
,
permission
);
}
else
if
(
status
.
isPermanentlyDenied
)
{
//第二次申请 用户拒绝
showPermissionAlert
(
widget
.
permissionList
[
2
],
"去设置中心"
,
permission
,
isSetting:
true
);
}
else
{
//通过
Navigator
.
of
(
context
).
pop
(
true
);
}
}
//是否去设置中心
bool
_isGoSetting
=
false
;
void
showPermissionAlert
(
String
message
,
String
rightString
,
Permission
permission
,
{
bool
isSetting
=
false
,
})
{
showDialog
(
builder:
(
BuildContext
context
)
{
return
AlertDialog
(
title:
const
Text
(
"温馨提示"
),
content:
Container
(
padding:
const
EdgeInsets
.
all
(
12
),
child:
Text
(
message
),
),
actions:
[
//左边的按钮
TextButton
(
child:
Text
(
widget
.
leftButtonText
),
onPressed:
()
{
if
(
widget
.
isCloseApp
)
{
closeApp
();
}
else
{
Navigator
.
of
(
context
).
pop
(
false
);
}
},
),
//右边的按钮
TextButton
(
child:
Text
(
rightString
),
onPressed:
()
{
//关闭弹框
Navigator
.
of
(
context
).
pop
();
if
(
isSetting
)
{
_isGoSetting
=
true
;
//去设置中心
openAppSettings
();
}
else
{
//申请权限
requestPermission
(
permission
);
}
},
)
],
);
},
context:
context
);
}
void
requestPermission
(
Permission
permission
)
async
{
//发起权限申请
PermissionStatus
status
=
await
permission
.
request
();
//校验
checkPermission
();
}
/// TODO 暂未使用
void
requestPermissionList
(
List
<
Permission
>
list
)
async
{
//多个权限申请
Map
<
Permission
,
PermissionStatus
>
statuses
=
await
[
Permission
.
location
,
Permission
.
storage
,
].
request
();
}
void
closeApp
()
{
//关闭应用的方法
SystemChannels
.
platform
.
invokeMethod
(
"SystemNavigator.pop"
);
}
@override
void
dispose
()
{
//注销观察者
if
(
WidgetsBinding
.
instance
!=
null
)
{
WidgetsBinding
.
instance
!.
removeObserver
(
this
);
}
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
const
Scaffold
(
backgroundColor:
Colors
.
transparent
,
);
}
}
lib/common/protocol_model.dart
0 → 100644
View file @
01d62a4
import
'package:flutter/gestures.dart'
;
import
'package:flutter/material.dart'
;
import
'package:one_poem/res/constant.dart'
;
import
'package:one_poem/routers/fluro_navigator.dart'
;
/// 创建人: Created by zhaolong
/// 创建时间:Created by on 2020/12/12.
///
/// 可关注公众号:我的大前端生涯 获取最新技术分享
/// 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm
/// 可关注博客:https://blog.csdn.net/zl18603543572
///
/// 代码清单
///代码清单
class
ProtocolModel
{
late
TapGestureRecognizer
_registerProtocolRecognizer
;
late
TapGestureRecognizer
_privacyProtocolRecognizer
;
///用来显示 用户协议对话框
Future
<
bool
>
showProtocolFunction
(
BuildContext
context
)
async
{
//注册协议的手势
_registerProtocolRecognizer
=
TapGestureRecognizer
();
//隐私协议的手势
_privacyProtocolRecognizer
=
TapGestureRecognizer
();
//苹果风格弹框
bool
isShow
=
await
showDialog
(
//上下文对象
context:
context
,
//对话框内容
builder:
(
BuildContext
context
)
{
return
showAlertDialog
(
context
);
},
);
///销毁
_registerProtocolRecognizer
.
dispose
();
_privacyProtocolRecognizer
.
dispose
();
return
Future
.
value
(
isShow
);
}
AlertDialog
showAlertDialog
(
BuildContext
context
)
{
return
AlertDialog
(
title:
const
Text
(
"温馨提示"
),
content:
Container
(
height:
260
,
padding:
const
EdgeInsets
.
all
(
1
),
//可滑动布局
child:
SingleChildScrollView
(
child:
buildContent
(
context
),
),
),
actions:
[
TextButton
(
child:
const
Text
(
"不同意"
),
onPressed:
()
{
Navigator
.
of
(
context
).
pop
(
false
);
},
),
TextButton
(
child:
const
Text
(
"同意"
),
onPressed:
()
{
Navigator
.
of
(
context
).
pop
(
true
);
},
),
],
);
}
//协议说明文案
String
userPrivateProtocol
=
"我们一向尊重并会严格保护用户在使用本产品时的合法权益(包括用户隐私、用户数据等)不受到任何侵犯。本协议(包括本文最后部分的隐私政策)是用户(包括通过各种合法途径获取到本产品的自然人、法人或其他组织机构,以下简称“用户”或“您”)与我们之间针对本产品相关事项最终的、完整的且排他的协议,并取代、合并之前的当事人之间关于上述事项的讨论和协议。本协议将对用户使用本产品的行为产生法律约束力,您已承诺和保证有权利和能力订立本协议。用户开始使用本产品将视为已经接受本协议,请认真阅读并理解本协议中各种条款,包括免除和限制我们的免责条款和对用户的权利限制(未成年人审阅时应由法定监护人陪同),如果您不能接受本协议中的全部条款,请勿开始使用本产品"
;
buildContent
(
BuildContext
context
)
{
return
RichText
(
text:
TextSpan
(
text:
"请您在使用本产品之前仔细阅读"
,
style:
TextStyle
(
color:
Colors
.
grey
[
600
]),
children:
[
TextSpan
(
text:
"《用户协议》"
,
style:
const
TextStyle
(
color:
Colors
.
blue
),
//点击事件
recognizer:
_registerProtocolRecognizer
..
onTap
=
()
{
//打开用户协议
openUserProtocol
(
context
);
},
),
TextSpan
(
text:
"与"
,
style:
TextStyle
(
color:
Colors
.
grey
[
600
]),
),
TextSpan
(
text:
"《隐私协议》"
,
style:
const
TextStyle
(
color:
Colors
.
blue
),
//点击事件
recognizer:
_privacyProtocolRecognizer
..
onTap
=
()
{
//打开隐私协议
openPrivateProtocol
(
context
);
},
),
TextSpan
(
text:
userPrivateProtocol
,
style:
TextStyle
(
color:
Colors
.
grey
[
600
]),
),
]),
);
}
//查看用户协议
void
openUserProtocol
(
BuildContext
context
)
{
NavigatorUtils
.
goWebViewPage
(
context
,
'用户协议'
,
Constant
.
protocolUrl
,
);
}
//查看隐私协议
void
openPrivateProtocol
(
BuildContext
context
)
{
NavigatorUtils
.
goWebViewPage
(
context
,
'隐私协议'
,
Constant
.
privacyUrl
,
);
}
}
lib/login/page/login_page.dart
View file @
01d62a4
import
'package:flustars/flustars.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:one_poem/common/permission_request_widget.dart'
;
import
'package:one_poem/common/protocol_model.dart'
;
import
'package:one_poem/home/webview_page.dart'
;
import
'package:one_poem/login/widgets/my_text_field.dart'
;
import
'package:one_poem/res/constant.dart'
;
import
'package:one_poem/res/resources.dart'
;
...
...
@@ -18,6 +22,8 @@ import '../login_router.dart';
import
'package:flutter_gen/gen_l10n/one_poem_localizations.dart'
;
import
'package:one_poem/extension/int_extension.dart'
;
import
'package:permission_handler/permission_handler.dart'
;
/// design/1注册登录/index.html
class
LoginPage
extends
StatefulWidget
{
const
LoginPage
({
Key
?
key
})
:
super
(
key:
key
);
...
...
@@ -27,7 +33,7 @@ class LoginPage extends StatefulWidget {
}
class
_LoginPageState
extends
State
<
LoginPage
>
with
ChangeNotifierMixin
<
LoginPage
>
{
with
ChangeNotifierMixin
<
LoginPage
>
,
ProtocolModel
{
//定义一个controller
final
TextEditingController
_nameController
=
TextEditingController
();
final
TextEditingController
_passwordController
=
TextEditingController
();
...
...
@@ -55,6 +61,40 @@ class _LoginPageState extends State<LoginPage>
overlays:
[
SystemUiOverlay
.
top
,
SystemUiOverlay
.
bottom
]);
});
_nameController
.
text
=
SpUtil
.
getString
(
Constant
.
phone
).
nullSafe
;
List
<
String
>
_list
=
[
"为您更好的体验应用,所以需要获取您的手机文件存储权限,以保存您的一些偏好设置"
,
"您已拒绝权限,所以无法保存您的一些偏好设置,将无法使用APP"
,
"您已拒绝权限,请在设置中心中同意APP的权限请求"
,
"其他错误"
];
Future
.
delayed
(
Duration
.
zero
,
()
{
NavigatorUtils
.
pushPageByFade
(
context:
context
,
//目标页面
targetPage:
PermissionRequestWidget
(
//所需要申请的权限
permission:
Permission
.
camera
,
//显示关闭应用按钮
isCloseApp:
true
,
//提示文案
permissionList:
_list
,
),
//权限申请结果
dismissCallBack:
(
value
)
{
showPrivacyPage
();
});
});
}
void
showPrivacyPage
()
async
{
bool
isAgreement
=
await
showProtocolFunction
(
context
);
if
(
isAgreement
)
{
// next();
}
else
{
SystemChannels
.
platform
.
invokeMethod
(
"SystemNavigator.pop"
);
}
}
void
_verify
()
{
...
...
@@ -125,6 +165,46 @@ class _LoginPageState extends State<LoginPage>
hintText:
OnePoemLocalizations
.
of
(
context
).
inputPasswordHint
,
),
Gaps
.
vGap24
,
Text
.
rich
(
TextSpan
(
text:
'登录即代表同意并阅读'
,
style:
const
TextStyle
(
fontSize:
12
,
color:
Color
(
0xFF999999
)),
children:
[
TextSpan
(
text:
'《用户协议》'
,
style:
TextStyle
(
color:
Theme
.
of
(
context
).
primaryColor
),
recognizer:
TapGestureRecognizer
()
..
onTap
=
()
{
Navigator
.
of
(
context
)
.
push
(
MaterialPageRoute
(
builder:
(
context
)
{
return
const
WebViewPage
(
title:
'《用户协议》'
,
url:
Constant
.
protocolUrl
,
);
}));
},
),
const
TextSpan
(
text:
'和'
),
TextSpan
(
text:
'《隐私政策》'
,
style:
TextStyle
(
color:
Theme
.
of
(
context
).
primaryColor
),
recognizer:
TapGestureRecognizer
()
..
onTap
=
()
{
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
context
)
{
return
const
WebViewPage
(
title:
'《隐私政策》'
,
url:
Constant
.
privacyUrl
,
);
},
),
);
},
),
]),
),
Gaps
.
vGap16
,
MyButton
(
key:
const
Key
(
'login'
),
onPressed:
_clickable
?
_login
:
null
,
...
...
lib/login/page/register_page.dart
View file @
01d62a4
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:one_poem/home/webview_page.dart'
;
import
'package:one_poem/login/widgets/my_text_field.dart'
;
import
'package:one_poem/res/resources.dart'
;
import
'package:one_poem/res/styles.dart'
;
...
...
@@ -32,6 +34,7 @@ class _RegisterPageState extends State<RegisterPage>
final
FocusNode
_nodeText2
=
FocusNode
();
final
FocusNode
_nodeText3
=
FocusNode
();
bool
_clickable
=
false
;
bool
_switchSelected
=
true
;
@override
Map
<
ChangeNotifier
,
List
<
VoidCallback
>?>?
changeNotifier
()
{
...
...
@@ -130,6 +133,39 @@ class _RegisterPageState extends State<RegisterPage>
keyboardType:
TextInputType
.
visiblePassword
,
hintText:
OnePoemLocalizations
.
of
(
context
).
inputPasswordHint
,
),
Gaps
.
vGap8
,
Text
.
rich
(
TextSpan
(
text:
'登录即代表同意并阅读'
,
style:
TextStyle
(
fontSize:
14
,
color:
const
Color
(
0xFF999999
)),
children:
[
TextSpan
(
text:
'《用户协议》'
,
style:
TextStyle
(
color:
Theme
.
of
(
context
).
primaryColor
),
recognizer:
TapGestureRecognizer
()
..
onTap
=
()
{
Navigator
.
of
(
context
)
.
push
(
MaterialPageRoute
(
builder:
(
context
)
{
return
WebViewPage
(
title:
'《用户协议》'
,
url:
'https://flutter.dev'
);
}));
},
),
TextSpan
(
text:
'和'
),
TextSpan
(
text:
'《隐私政策》'
,
style:
TextStyle
(
color:
Theme
.
of
(
context
).
primaryColor
),
recognizer:
TapGestureRecognizer
()
..
onTap
=
()
{
Navigator
.
of
(
context
)
.
push
(
MaterialPageRoute
(
builder:
(
context
)
{
return
WebViewPage
(
title:
'《隐私政策》'
,
url:
'https://flutter.dev'
);
}));
},
),
]),
),
Gaps
.
vGap24
,
MyButton
(
key:
const
Key
(
'register'
),
...
...
lib/res/constant.dart
View file @
01d62a4
...
...
@@ -2,6 +2,9 @@ import 'package:flutter/foundation.dart';
class
Constant
{
static
const
String
privacyUrl
=
"https://www.mofunenglish.com/index.php?act=about&mdl=agreement"
;
static
const
String
protocolUrl
=
"https://www.mofunenglish.com/index.php?act=about&mdl=agreement"
;
/// App运行在Release环境时,inProduction为true;当App运行在Debug和Profile环境时,inProduction为false
static
const
bool
inProduction
=
kReleaseMode
;
...
...
lib/routers/fluro_navigator.dart
View file @
01d62a4
...
...
@@ -5,11 +5,12 @@ import 'routers.dart';
/// fluro的路由跳转工具类
class
NavigatorUtils
{
static
void
push
(
BuildContext
context
,
String
path
,
{
bool
replace
=
false
,
bool
clearStack
=
false
,
Object
?
arguments
})
{
unfocus
();
Routes
.
router
.
navigateTo
(
context
,
path
,
Routes
.
router
.
navigateTo
(
context
,
path
,
replace:
replace
,
clearStack:
clearStack
,
transition:
TransitionType
.
native
,
...
...
@@ -19,17 +20,22 @@ class NavigatorUtils {
);
}
static
void
pushResult
(
BuildContext
context
,
String
path
,
Function
(
Object
)
function
,
static
void
pushResult
(
BuildContext
context
,
String
path
,
Function
(
Object
)
function
,
{
bool
replace
=
false
,
bool
clearStack
=
false
,
Object
?
arguments
})
{
unfocus
();
Routes
.
router
.
navigateTo
(
context
,
path
,
Routes
.
router
.
navigateTo
(
context
,
path
,
replace:
replace
,
clearStack:
clearStack
,
transition:
TransitionType
.
native
,
routeSettings:
RouteSettings
(
arguments:
arguments
,
),
).
then
((
Object
?
result
)
{
)
.
then
((
Object
?
result
)
{
// 页面返回result为null
if
(
result
==
null
)
{
return
;
...
...
@@ -51,11 +57,12 @@ class NavigatorUtils {
unfocus
();
Navigator
.
pop
<
Object
>(
context
,
result
);
}
/// 跳到WebView页
static
void
goWebViewPage
(
BuildContext
context
,
String
title
,
String
url
)
{
//fluro 不支持传中文,需转换
push
(
context
,
'
${Routes.webViewPage}
?title=
${Uri.encodeComponent(title)}
&url=
${Uri.encodeComponent(url)}
'
);
push
(
context
,
'
${Routes.webViewPage}
?title=
${Uri.encodeComponent(title)}
&url=
${Uri.encodeComponent(url)}
'
);
}
static
void
unfocus
()
{
...
...
@@ -64,4 +71,50 @@ class NavigatorUtils {
// https://github.com/flutter/flutter/issues/47128#issuecomment-627551073
FocusManager
.
instance
.
primaryFocus
?.
unfocus
();
}
///普通打开页面的方法
///[context] 上下文对象
///[targetPage] 目标页面
///[isReplace] 是否替换当前页面 A -B
///[opaque] 是否以背景透明的方式打开页面
static
void
pushPageByFade
({
required
BuildContext
context
,
required
Widget
targetPage
,
bool
isReplace
=
false
,
int
startMills
=
400
,
bool
opaque
=
false
,
Function
(
dynamic
value
)?
dismissCallBack
,
})
{
PageRoute
pageRoute
=
PageRouteBuilder
(
//背景透明 方式打开新的页面
opaque:
opaque
,
pageBuilder:
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
)
{
return
targetPage
;
},
transitionDuration:
Duration
(
milliseconds:
startMills
),
//动画
transitionsBuilder:
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
FadeTransition
(
opacity:
animation
,
child:
child
,
);
},
);
if
(
isReplace
)
{
Navigator
.
of
(
context
).
pushReplacement
(
pageRoute
).
then
((
value
)
{
if
(
dismissCallBack
!=
null
)
{
dismissCallBack
(
value
);
}
});
}
else
{
Navigator
.
of
(
context
).
push
(
pageRoute
).
then
((
value
)
{
if
(
dismissCallBack
!=
null
)
{
dismissCallBack
(
value
);
}
});
}
}
}
...
...
pubspec.lock
View file @
01d62a4
...
...
@@ -708,6 +708,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.11.1"
permission_handler:
dependency: "direct dev"
description:
name: permission_handler
url: "https://pub.dartlang.org"
source: hosted
version: "8.3.0"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.7.0"
petitparser:
dependency: transitive
description:
...
...
pubspec.yaml
View file @
01d62a4
...
...
@@ -129,6 +129,8 @@ dev_dependencies:
flutter_launcher_icons
:
^0.9.2
flutter_native_splash
:
^1.3.2
permission_handler
:
^8.3.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
...
...
Please
register
or
login
to post a comment