Flutter 實現(xiàn)隱私政策

《用戶協(xié)議》和《隱私政策》已經(jīng)是一款A(yù)pp的標(biāo)配,通常在登錄/注冊界面需要展示,現(xiàn)在更加嚴(yán)格的監(jiān)管要求App在獲取一些權(quán)限之前必須像用戶展示《隱私政策》說明,這也是大部分App在第一次安裝啟動頁面時會彈出《隱私政策》彈窗,用戶點擊同意后方可獲取權(quán)限。
先來看下登錄/注冊界面通常展示的《用戶協(xié)議》和《隱私政策》,代碼實現(xiàn)如下:
Text.rich(
TextSpan(
text: '登錄即代表同意并閱讀',
style: TextStyle(fontSize: 14, color: Color(0xFF999999)),
children: [
TextSpan(
text: '《用戶協(xié)議》',
style: TextStyle(color: Theme.of(context).primaryColor),
recognizer: TapGestureRecognizer()
..onTap = () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return WebViewPage(
title: '《用戶協(xié)議》', 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');
}));
},
),
]),
)
通常情況下,點擊《用戶協(xié)議》和《隱私政策》會跳轉(zhuǎn)到相應(yīng)的H5,上面跳轉(zhuǎn)到flutter官網(wǎng)。

下面看看彈窗的,效果如下:

首先可以按照簡單的方式實現(xiàn),自己手動找出《用戶協(xié)議》和《隱私政策》,但這樣做有一個比較麻煩的情況是,一旦修改,需要重新拼接,耗時而且容易出錯,所以下面我們實現(xiàn)一個自動查找《用戶協(xié)議》和《隱私政策》的功能,代碼如下:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
typedef OnTapCallback = void Function(String key);
class PrivacyView extends StatefulWidget {
final String data;
final List<String> keys;
final TextStyle? style;
final TextStyle? keyStyle;
final OnTapCallback? onTapCallback;
const PrivacyView({
Key? key,
required this.data,
required this.keys,
this.style,
this.keyStyle,
this.onTapCallback,
}) : super(key: key);
@override
_PrivacyViewState createState() => _PrivacyViewState();
}
class _PrivacyViewState extends State<PrivacyView> {
List<String> _list = [];
@override
void initState() {
_split();
super.initState();
}
@override
Widget build(BuildContext context) {
return RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <InlineSpan>[
..._list.map((e) {
if (widget.keys.contains(e)) {
return TextSpan(
text: '$e',
style: widget.keyStyle ??
TextStyle(color: Theme.of(context).primaryColor),
recognizer: TapGestureRecognizer()
..onTap = () {
widget.onTapCallback?.call(e);
},
);
} else {
return TextSpan(text: '$e', style: widget.style);
}
}).toList()
]),
);
}
void _split() {
int startIndex = 0;
Map<String, dynamic>? _index;
while ((_index = _nextIndex(startIndex)) != null) {
int i = _index?['index'];
String sub = widget.data.substring(startIndex, i);
if (sub.isNotEmpty) {
_list.add(sub);
}
_list.add(_index?['key']);
startIndex = i + (_index?['key'] as String).length;
}
}
Map<String, dynamic>? _nextIndex(int startIndex) {
int currentIndex = widget.data.length;
String? key;
widget.keys.forEach((element) {
int index = widget.data.indexOf(element, startIndex);
if (index != -1 && index < currentIndex) {
currentIndex = index;
key = element;
}
});
if (key == null) {
return null;
}
return {'key': '$key', 'index': currentIndex};
}
}
彈窗實現(xiàn):
String _data = "親愛的xxxx用戶,感謝您信任并使用xxxxAPP!\n" +
" \n" +
"xxxx十分重視用戶權(quán)利及隱私政策并嚴(yán)格按照相關(guān)法律法規(guī)的要求,對《用戶協(xié)議》和《隱私政策》進行了更新,特向您說明如下:\n" +
"1.為向您提供更優(yōu)質(zhì)的服務(wù),我們會收集、使用必要的信息,并會采取業(yè)界先進的安全措施保護您的信息安全;\n" +
"2.基于您的明示授權(quán),我們可能會獲取設(shè)備號信息、包括:設(shè)備型號、操作系統(tǒng)版本、設(shè)備設(shè)置、設(shè)備標(biāo)識符、MAC(媒體訪問控制)地址、IMEI(移動設(shè)備國際身份碼)、廣告標(biāo)識符(“IDFA”與“IDFV”)、集成電路卡識別碼(“ICCD”)、軟件安裝列表。我們將使用三方產(chǎn)品(友盟、極光等)統(tǒng)計使用我們產(chǎn)品的設(shè)備數(shù)量并進行設(shè)備機型數(shù)據(jù)分析與設(shè)備適配性分析。(以保障您的賬號與交易安全),且您有權(quán)拒絕或取消授權(quán);\n" +
"3.您可靈活設(shè)置伴伴賬號的功能內(nèi)容和互動權(quán)限,您可在《隱私政策》中了解到權(quán)限的詳細應(yīng)用說明;\n" +
"4.未經(jīng)您同意,我們不會從第三方獲取、共享或向其提供您的信息;\n" +
"5.您可以查詢、更正、刪除您的個人信息,我們也提供賬戶注銷的渠道。\n" +
" \n" +
"請您仔細閱讀并充分理解相關(guān)條款,其中重點條款已為您黑體加粗標(biāo)識,方便您了解自己的權(quán)利。如您點擊“同意”,即表示您已仔細閱讀并同意本《用戶協(xié)議》及《隱私政策》,將盡全力保障您的合法權(quán)益并繼續(xù)為您提供優(yōu)質(zhì)的產(chǎn)品和服務(wù)。如您點擊“不同意”,將可能導(dǎo)致您無法繼續(xù)使用我們的產(chǎn)品和服務(wù)。";
showGeneralDialog(
context: context,
barrierDismissible: true,
barrierLabel: '',
transitionDuration: Duration(milliseconds: 200),
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return Center(
child: Material(
child: Container(
height: MediaQuery.of(context).size.height * .6,
width: MediaQuery.of(context).size.width * .8,
child: Column(
children: [
Container(
height: 45,
alignment: Alignment.center,
child: Text(
'用戶隱私政策概要',
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
),
Divider(
height: 1,
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: PrivacyView(
data: _data,
keys: ['《用戶協(xié)議》', '《隱私政策》'],
keyStyle: TextStyle(color: Colors.red),
onTapCallback: (String key) {
if (key == '《用戶協(xié)議》') {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return WebViewPage(
title: key, url: 'https://flutter.dev');
}));
} else if (key == '《隱私政策》') {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return WebViewPage(
title: key, url: 'https://www.baidu.com');
}));
}
},
),
),
)),
Divider(
height: 1,
),
Container(
height: 45,
child: Row(
children: [
Expanded(
child: GestureDetector(
child: Container(
alignment: Alignment.center,
child: Text('不同意')),
onTap: () {},
)),
VerticalDivider(
width: 1,
),
Expanded(
child: GestureDetector(
child: Container(
alignment: Alignment.center,
color: Theme.of(context).primaryColor,
child: Text('同意')),
onTap: () {},
)),
],
),
),
],
),
),
),
);
});


評論
圖片
表情
