|
|
import 'dart:convert';
|
|
|
import 'dart:developer' as developer;
|
|
|
import 'dart:io';
|
|
|
import 'dart:math';
|
|
|
|
|
|
import 'package:camera/camera.dart';
|
|
|
import 'package:convert/convert.dart';
|
|
|
import 'package:crypto/crypto.dart' as crypto;
|
|
|
import 'package:device_info/device_info.dart';
|
|
|
import 'package:flutter/material.dart';
|
|
|
import 'package:flutter/services.dart';
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
|
//import '../my_wechat_assets_picker_fix/my_asset_picker_1.dart';
|
|
|
import 'package:fluttertoast/fluttertoast.dart';
|
|
|
import 'package:hyzp_ybqx04_changning/provider/player_region.dart';
|
|
|
|
|
|
import 'UserInfo.dart';
|
|
|
|
|
|
////////////////////////////////////////////
|
|
|
// begin hyzp_ybqx-Commit022-区县切换新方法-OK
|
|
|
|
|
|
// 1、修改手机桌面的App图标文本
|
|
|
// R:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\AndroidManifest.xml
|
|
|
// android:label="宜宾黑烟抓拍"
|
|
|
// android:label="宜宾市翠屏黑烟抓拍"
|
|
|
// android:label="宜宾市兴文黑烟抓拍"
|
|
|
// android:label="宜宾市筠连黑烟抓拍"
|
|
|
// android:label="宜宾市长宁黑烟抓拍"
|
|
|
|
|
|
// 2、修改App的android和Flutter启动图片,制作并运行 hyzp_ybqx04_changning.images_copy.cmd,自动完成两项拷贝任务
|
|
|
// (1)、拷贝不同分辨率的图片文件hyzp_ybqx04_changning_launche.png到下面目录,作为App的android启动图片
|
|
|
// r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-hdpi\
|
|
|
// r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-mdpi\
|
|
|
// r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-xhdpi\
|
|
|
// r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-xxhdpi\
|
|
|
// r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\android\app\src\main\res\mipmap-xxxhdpi\
|
|
|
// (2)、拷贝 750 * 1334 的图片文件到下面目录,作为App的Flutter启动图片
|
|
|
// r:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\assets\images\hyzp_ybqx01_cuiping_launche.png
|
|
|
|
|
|
// 3、修改文本变量
|
|
|
// 位于文件 R:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\lib\components\commonFun.dart 中
|
|
|
// (1)、宜宾市
|
|
|
// String service_tel = '\n服务热线:187-8467-8300';
|
|
|
// String yibin_QuXian = '宜宾';
|
|
|
// String copyright_info = '© ' + yibin_QuXian + '市生态环境局 四川省踏石科技有限公司 版权所有' + service_tel;
|
|
|
// String copyright_info_PinYin = 'YIBIN BLACK SMOKE CAR CAPTURE SYSTEM';
|
|
|
|
|
|
// (2)、翠屏区
|
|
|
// String service_tel = '';
|
|
|
// String yibin_QuXian = '宜宾市翠屏';
|
|
|
// String copyright_info = '© ' + yibin_QuXian + '生态环境局 版权所有' + service_tel;
|
|
|
// String copyright_info_PinYin = 'YIBIN CUIPING BLACK SMOKE CAR CAPTURE SYSTEM';
|
|
|
|
|
|
// (3)、兴文县
|
|
|
// String service_tel = '\n服务热线:187-8467-8300';
|
|
|
// String yibin_QuXian = '宜宾市兴文';
|
|
|
// String copyright_info = '© ' + yibin_QuXian + '生态环境局 四川省踏石科技 版权所有' + service_tel;
|
|
|
// String copyright_info_PinYin = 'YIBIN XINGWEN BLACK SMOKE CAR CAPTURE SYSTEM';
|
|
|
|
|
|
// (4)、筠连县
|
|
|
// String service_tel = '\n服务热线:187-8467-8300';
|
|
|
// String yibin_QuXian = '宜宾市筠连';
|
|
|
// String copyright_info = '© ' + yibin_QuXian + '生态环境局 四川省踏石科技 版权所有' + service_tel;
|
|
|
// String copyright_info_PinYin = 'YIBIN JUNLIAN BLACK SMOKE CAR CAPTURE SYSTEM';
|
|
|
|
|
|
// (5)、长宁县
|
|
|
String service_tel = '';
|
|
|
String yibin_QuXian = '宜宾市长宁';
|
|
|
String copyright_info = '© ' + yibin_QuXian + '生态环境局 版权所有' + service_tel;
|
|
|
String copyright_info_PinYin = 'YIBIN CHANGNING BLACK SMOKE CAR CAPTURE SYSTEM';
|
|
|
|
|
|
// 4、全局替换,将 ”hyzp_ybqx04_changning“全部替换为 ”hyzp_ybqx04_changning“,自动完成以下修改
|
|
|
// (1)、修改 R:\FlutterProject\FlutterProject51-hyzp_ybqx\hyzp_ybqx\pubspec.yaml 文件中的AppID,但存放目錄不變
|
|
|
// name: hyzp_ybqx00_yibin
|
|
|
// name: hyzp_ybqx01_cuiping
|
|
|
// name: hyzp_ybqx04_changning
|
|
|
// (2)、全局替换:
|
|
|
// A、将 “com.flutter.hyzp_ybqx00_yibin” 全部替换为 “com.flutter.hyzp_ybqx04_changning”
|
|
|
// B、将 “package:hyzp_ybqx00_yibin/” 全部替换为 “package:hyzp_ybqx04_changning/”
|
|
|
// C、将 “# hyzp_ybqx00_yibin” 全部替换为 “# hyzp_ybqx04_changning”
|
|
|
// D、将 “<string>hyzp_ybqx00_yibin</string>” 全部替换为 “<string>hyzp_ybqx04_changning</string>”
|
|
|
|
|
|
// 5、完成以上修改后,打开 Android Studio 的终端窗口,切换到项目的 lib 目录下,运行 flutter clean
|
|
|
|
|
|
// 6、重新编译运行App
|
|
|
|
|
|
// end hyzp_ybqx-Commit022-区县切换新方法-OK
|
|
|
////////////////////////////////////////////
|
|
|
|
|
|
//LED字幕信息
|
|
|
//String g_ledMessage = '绿水青山就是金山银山 宜宾市翠屏生态环境局宣。';
|
|
|
|
|
|
// 是否已经调用 FlutterDownloader.initialize(debug: true)
|
|
|
bool bFlutterDownloader_initialize = false;
|
|
|
bool bNewVer = false; //是否发现新版本
|
|
|
|
|
|
//处理延时登录,判断从网络获取三种统计数据是否完成
|
|
|
bool bMayLogin = false;
|
|
|
//处理延时登录,判断是否已经点击登录按钮
|
|
|
bool bPreLoading = false;
|
|
|
//处理延时登录,判断用户名登录是否验证通过
|
|
|
bool bLoginVerify = false;
|
|
|
|
|
|
bool bHasMore = true;
|
|
|
|
|
|
//part library
|
|
|
//dart中,通过使用part、part of、library来实现拆分库,这样,就可以将一个庞大的库拆分成各种小库,只要引用主库即可
|
|
|
|
|
|
//点位总数
|
|
|
int dwSum = -1;
|
|
|
|
|
|
Size sizeWindowPhysicalSize;
|
|
|
|
|
|
//String dateAppCompile = '2020.12.30'; //1.0.1+1
|
|
|
//String dateAppCompile = '2021.02.20'; //1.2.5+1
|
|
|
//String dateAppCompile = '2021.03.18'; //1.2.6+1
|
|
|
//String dateAppCompile = '2021.05.18'; //1.2.7
|
|
|
List<String> g_list = [];
|
|
|
|
|
|
//正在获取点位视频标志,禁止重入
|
|
|
bool getingDwVideo = false;
|
|
|
int getCount = 1; //获取点位视频地址尝试次数
|
|
|
int getSumTime = 0; //获取点位视频地址耗时(秒)
|
|
|
int getingIndex = -1; //正在获取视频的点位的索引号
|
|
|
String getingDwmc = ''; //正在获取视频的点位名称
|
|
|
String urlnew =
|
|
|
"http://www.yibinu.edu.cn/__local/5/35/DF/264049B7E978EEE2F5849688986_05D4A6FE_152CDB8C.mp4?e=.mp4";
|
|
|
|
|
|
bool isVideoUrl(String url, {bool showToast = false}) {
|
|
|
print('url = $url');
|
|
|
String prefix = url.substring(0, 4);
|
|
|
List list = ['http', 'rtmp', 'rstp'];
|
|
|
for (String item in list) {
|
|
|
if (prefix == item) {
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (showToast) {
|
|
|
Fluttertoast.showToast(
|
|
|
msg: '获取视频地址失败',
|
|
|
toastLength: Toast.LENGTH_SHORT,
|
|
|
gravity: ToastGravity.CENTER,
|
|
|
);
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
final TextEditingController myController = TextEditingController();
|
|
|
|
|
|
bool Playing = false; //禁止同时启动两次播放器
|
|
|
|
|
|
//final FijkPlayer player = FijkPlayer();
|
|
|
int g_iIndex = 0;
|
|
|
PlayerRegionProvide playerRegionProvide;
|
|
|
|
|
|
Future<void> sysPop() async {
|
|
|
// currentPos = player.currentPos.inMilliseconds; //seekto方法的参数是毫秒
|
|
|
// await writeCurrentPosFile();
|
|
|
// await player.stop();
|
|
|
await SystemChannels.platform.invokeMethod('SystemNavigator.pop');
|
|
|
}
|
|
|
|
|
|
//人脸注册和人脸识别登录成功标志
|
|
|
int faceReg = -1; //1 成功,0 失败,-1 处理中
|
|
|
int faceLogin = -1; //1 成功,0 失败,-1 处理中
|
|
|
|
|
|
//人脸注册时所需用户ID
|
|
|
int faceRegUserID = -1; //人脸注册时所需用户ID,-1 非法
|
|
|
|
|
|
List<CameraDescription> cameras;
|
|
|
UserInfo g_userInfo = UserInfo(mapUserInfoRet: {
|
|
|
"ret": 200,
|
|
|
"data": {
|
|
|
"is_login": true,
|
|
|
"user_id": 1,
|
|
|
"token": "B93EC91FA2FE293B7077162D4527FC4BB228CD6C0A4F24A882B9A8BBE6C3FB47"
|
|
|
},
|
|
|
"msg": ""
|
|
|
});
|
|
|
|
|
|
Future<Map> getMapFromJson(var response) async {
|
|
|
String _str = json.encode(response);
|
|
|
Map _map = json.decode(_str);
|
|
|
return _map;
|
|
|
}
|
|
|
|
|
|
// Future<void> getVideoList(BuildContext context) async {
|
|
|
// List<AssetEntity> assets = <AssetEntity>[];
|
|
|
// return await MyAssetPicker.pickAssets(
|
|
|
// context,
|
|
|
// maxAssets: 1,
|
|
|
// selectedAssets: assets,
|
|
|
// requestType: RequestType.video,
|
|
|
// );
|
|
|
// }
|
|
|
|
|
|
Future<String> getAndroidId() async {
|
|
|
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
|
|
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
|
|
//print('每个手机唯一的设备号:${androidInfo.androidId}'); // e.g. "Moto G (4)"
|
|
|
g_userInfo.thisAndroidId = androidInfo.androidId;
|
|
|
return g_userInfo.thisAndroidId;
|
|
|
}
|
|
|
|
|
|
// void playOrPause() {
|
|
|
// playerRegionProvide.changePlayerState(bPlaying);
|
|
|
//
|
|
|
// if (bPlaying) {
|
|
|
// player.start();
|
|
|
// } else {
|
|
|
// player.pause();
|
|
|
// }
|
|
|
//
|
|
|
// Storage.setString('bFirstPlay', bFirstPlay ? 'true' : 'false');
|
|
|
// Storage.setString('bPlaying', bPlaying ? 'true' : 'false');
|
|
|
//
|
|
|
// //updateFile();
|
|
|
// }
|
|
|
//
|
|
|
// void playAndPause() {
|
|
|
// if (player.state == FijkState.started) {
|
|
|
// bPlaying = false;
|
|
|
// player.pause();
|
|
|
// } else if (player.state == FijkState.paused) {
|
|
|
// bPlaying = true;
|
|
|
// player.start();
|
|
|
// }
|
|
|
// //setState(() {});
|
|
|
// playerRegionProvide.changePlayerState(bPlaying);
|
|
|
// Storage.setString('bPlaying', bPlaying ? 'true' : 'false');
|
|
|
// }
|
|
|
|
|
|
Alignment getAlignment(Offset offset, Size size) {
|
|
|
// final double centerX = offset.dx / 2.0;
|
|
|
// final double centerY = offset.dy / 2.0;
|
|
|
|
|
|
//offset.dx = centerX + alignment.x * centerX;
|
|
|
//double alignmentX = (0.0 == centerX) ? 0.0 : ((offset.dx - centerX) / centerX);
|
|
|
double alignmentX = (offset.dx / size.width).clamp(-1.0, 1.0);
|
|
|
|
|
|
//offset.dy = centerY + alignment.y * centerY;
|
|
|
//double alignmentY = (0.0 == centerY) ? 0.0 : ((offset.dy - centerY) / centerY);
|
|
|
double alignmentY = (offset.dy / size.height).clamp(-1.0, 1.0);
|
|
|
|
|
|
// print('offset.dx = ${offset.dx}, offset.dy = ${offset.dy}');
|
|
|
print('Alignment.X = $alignmentX, Alignment.Y = $alignmentY');
|
|
|
return Alignment(alignmentX, alignmentY);
|
|
|
}
|
|
|
|
|
|
//flutter (dart)生成N位随机数
|
|
|
//https://blog.csdn.net/qq_36071410/article/details/101268640
|
|
|
// 庄童 2019-09-24 10:24:58 10271 收藏
|
|
|
String RandomBit(int len) {
|
|
|
String scopeF = '123456789'; //首位
|
|
|
String scopeC = '0123456789'; //中间
|
|
|
String result = '';
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
if (i == 0) {
|
|
|
result = scopeF[Random().nextInt(scopeF.length)];
|
|
|
} else {
|
|
|
result = result + scopeC[Random().nextInt(scopeC.length)];
|
|
|
}
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
// sign=md5(ijddvzgEGaxbzsbmCtpdohxHyrAArwJB1003)
|
|
|
// =3967eaebec0eed0642a1d395ac9293dd
|
|
|
String APPkey = 'ijddvzgEGaxbzsbmCtpdohxHyrAArwJB';
|
|
|
//Flutter对字符串进行MD5运算 发表于 2019-03-26 更新于 2020-12-04 分类于 Flutter 阅读次
|
|
|
String GenerateMd5(String str) {
|
|
|
var content = new Utf8Encoder().convert(str);
|
|
|
var md5 = crypto.md5;
|
|
|
var digest = md5.convert(content);
|
|
|
return hex.encode(digest.bytes);
|
|
|
}
|
|
|
|
|
|
//加载中的圈圈
|
|
|
Widget getMoreWidget2({
|
|
|
Color color = Colors.white,
|
|
|
String text = '加载中...',
|
|
|
double size = 30.0,
|
|
|
double strokeWidth = 3.0,
|
|
|
FontWeight fontWeight,
|
|
|
double edge = 10.0,
|
|
|
double height = 34,
|
|
|
}) {
|
|
|
return Center(
|
|
|
child: Padding(
|
|
|
padding: EdgeInsets.all(edge),
|
|
|
child: Column(
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
children: <Widget>[
|
|
|
SizedBox(
|
|
|
height: size,
|
|
|
width: size,
|
|
|
child: CircularProgressIndicator(
|
|
|
strokeWidth: strokeWidth,
|
|
|
valueColor: AlwaysStoppedAnimation<Color>(color),
|
|
|
),
|
|
|
),
|
|
|
SizedBox(
|
|
|
height: ScreenUtil().setHeight(height),
|
|
|
),
|
|
|
Text(
|
|
|
text,
|
|
|
textAlign: TextAlign.center,
|
|
|
style: TextStyle(
|
|
|
fontSize: size, // 文字大小
|
|
|
color: color,
|
|
|
fontWeight: fontWeight, // 文字颜色
|
|
|
),
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//加载中的圈圈
|
|
|
Widget getMoreWidget({
|
|
|
String text = '加载中...',
|
|
|
Color color = Colors.white,
|
|
|
double size = 30.0,
|
|
|
double strokeWidth = 3.0,
|
|
|
TextAlign textAlign = TextAlign.left,
|
|
|
}) {
|
|
|
return Center(
|
|
|
child: Padding(
|
|
|
padding: EdgeInsets.all(10.0),
|
|
|
child: Column(
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
children: <Widget>[
|
|
|
SizedBox(
|
|
|
height: size,
|
|
|
width: size,
|
|
|
child: CircularProgressIndicator(
|
|
|
strokeWidth: strokeWidth,
|
|
|
valueColor: AlwaysStoppedAnimation<Color>(color),
|
|
|
),
|
|
|
),
|
|
|
SizedBox(
|
|
|
height: 10,
|
|
|
),
|
|
|
Text(
|
|
|
text,
|
|
|
textAlign: textAlign,
|
|
|
style: TextStyle(
|
|
|
fontSize: size, // 文字大小
|
|
|
color: color,
|
|
|
),
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//自定义带说明图标按钮函数。点击说明文字有反应
|
|
|
Widget getIconAndTextButton(
|
|
|
{IconData iconData, Color iconColor = Colors.black, var onPress = null}) {
|
|
|
return Container(
|
|
|
width: 50,
|
|
|
height: 50,
|
|
|
alignment: const Alignment(0, 0),
|
|
|
child: FlatButton(
|
|
|
padding: EdgeInsets.all(0),
|
|
|
onPressed: onPress,
|
|
|
//color: Colors.blue,
|
|
|
color: Colors.transparent,
|
|
|
//解决报错问题:FittedBox ← Expanded ← ConstrainedBox ← Container ← Center ← Padding ←
|
|
|
// Container ← IconTheme ← Builder ← _PointerListener
|
|
|
child: ConstrainedBox(
|
|
|
constraints: BoxConstraints(
|
|
|
maxHeight: 36, //最大高度
|
|
|
maxWidth: 36, //最大宽度
|
|
|
),
|
|
|
child: Padding(
|
|
|
padding: EdgeInsets.only(top: 1),
|
|
|
child: Icon(iconData, color: iconColor, size: 32),
|
|
|
// child: Image.asset(
|
|
|
// 'assets/images/left_arrow.png',
|
|
|
// fit: BoxFit.fitWidth,
|
|
|
// color: iconColor,
|
|
|
// //fit: BoxFit.cover,
|
|
|
// ),
|
|
|
),
|
|
|
|
|
|
// child: Row(
|
|
|
// mainAxisAlignment: MainAxisAlignment.center,
|
|
|
// crossAxisAlignment: CrossAxisAlignment.end,
|
|
|
// children: [
|
|
|
// Image.asset('assets/images/left_arrow.png', fit: BoxFit.cover),
|
|
|
// // Expanded(
|
|
|
// // //child: Icon(iconData, color: iconColor, size: 24),
|
|
|
// // child: Image.asset('assets/images/left_arrow.png', fit: BoxFit.cover),
|
|
|
// // ),
|
|
|
// ],
|
|
|
// ),
|
|
|
),
|
|
|
|
|
|
//The offending Expanded is currently placed inside a ConstrainedBox widget.
|
|
|
//The ownership chain for the RenderObject that received the incompatible parent data was:
|
|
|
// FittedBox ← Expanded ← ConstrainedBox ← Container ← Center ← Padding ← Container ← IconTheme ←
|
|
|
//Builder ← _PointerListener
|
|
|
|
|
|
//The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a
|
|
|
//RenderObject, which has been set up to accept ParentData of incompatible type ParentData.
|
|
|
//Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically,
|
|
|
//Expanded widgets are placed directly inside Flex widgets.
|
|
|
//The offending Expanded is currently placed inside a FittedBox widget.
|
|
|
//The ownership chain for the RenderObject that received the incompatible parent data was:
|
|
|
// ConstrainedBox ← Container ← Expanded ← FittedBox ← Center ← Padding ← Container ← IconTheme ←
|
|
|
//Builder ← _PointerListener ← ⋯
|
|
|
// child: ConstrainedBox(
|
|
|
// constraints: BoxConstraints(
|
|
|
// maxHeight: 20, //最大高度
|
|
|
// maxWidth: 28, //最大宽度
|
|
|
// ),
|
|
|
// child: Container(
|
|
|
// child: Expanded(
|
|
|
// child: new Icon(iconData, color: iconColor),
|
|
|
// ),
|
|
|
// ),
|
|
|
// ),
|
|
|
|
|
|
// child: ConstrainedBox(
|
|
|
// constraints: BoxConstraints(
|
|
|
// maxHeight: 30, //最大高度
|
|
|
// maxWidth: 38, //最大宽度
|
|
|
// minWidth: 38, //最大宽度
|
|
|
// ),
|
|
|
// child: Row(
|
|
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
// children: [
|
|
|
// Expanded(
|
|
|
// child: Icon(iconData, color: iconColor, size: 24),
|
|
|
// ),
|
|
|
// ],
|
|
|
// ),
|
|
|
// ),
|
|
|
|
|
|
// child: Container(
|
|
|
// width: 28,
|
|
|
// height: 20,
|
|
|
// child: Expanded(
|
|
|
// child: new FittedBox(
|
|
|
// fit: BoxFit.fill,
|
|
|
// child: new Icon(iconData, color: iconColor),
|
|
|
// ),
|
|
|
// ),
|
|
|
// ),
|
|
|
|
|
|
// child: FittedBox(
|
|
|
// fit: BoxFit.fitWidth,
|
|
|
// alignment: Alignment.topLeft,
|
|
|
// child: Container(
|
|
|
// width: 28,
|
|
|
// height: 20,
|
|
|
// child: Expanded(
|
|
|
// child: new FittedBox(
|
|
|
// fit: BoxFit.fill,
|
|
|
// child: new Icon(iconData, color: iconColor),
|
|
|
// ),
|
|
|
// ),
|
|
|
// ),
|
|
|
// ),
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
///获取缩进空白符
|
|
|
String getDeepSpace(int deep) {
|
|
|
var tab = StringBuffer();
|
|
|
for (int i = 0; i < deep; i++) {
|
|
|
tab.write("\t");
|
|
|
}
|
|
|
return tab.toString();
|
|
|
}
|
|
|
|
|
|
// List map2list(Map _map) {
|
|
|
// List _list = [];
|
|
|
// _list = List.generate(listContacts2[widget.contactIndex].length, (index) {
|
|
|
// String key = listContacts2[widget.contactIndex].keys.elementAt(index);
|
|
|
// //return TextEditingController(text: listContacts2[widget.contactIndex][key]);
|
|
|
// return TextEditingController(text: getUserText3(widget.contactIndex, key));
|
|
|
// });
|
|
|
//
|
|
|
// }
|
|
|
|
|
|
/// [object] 解析的对象
|
|
|
/// [deep] 递归的深度,用来获取缩进的空白长度
|
|
|
/// [isObject] 用来区分当前map或list是不是来自某个字段,则不用显示缩进。单纯的map或list需要添加缩进
|
|
|
String json_print(dynamic object, int deep, {bool isObject = false}) {
|
|
|
var buffer = StringBuffer();
|
|
|
var nextDeep = deep + 1;
|
|
|
if (object is Map) {
|
|
|
var list = object.keys.toList();
|
|
|
if (!isObject) {
|
|
|
//如果map来自某个字段,则不需要显示缩进
|
|
|
buffer.write("${getDeepSpace(deep)}");
|
|
|
}
|
|
|
buffer.write("{");
|
|
|
if (list.isEmpty) {
|
|
|
//当map为空,直接返回‘}’
|
|
|
buffer.write("}");
|
|
|
} else {
|
|
|
buffer.write("\n");
|
|
|
for (int i = 0; i < list.length; i++) {
|
|
|
buffer.write("${getDeepSpace(nextDeep)}\"${list[i]}\":");
|
|
|
buffer.write(json_print(object[list[i]], nextDeep, isObject: true));
|
|
|
if (i < list.length - 1) {
|
|
|
buffer.write(",");
|
|
|
buffer.write("\n");
|
|
|
}
|
|
|
}
|
|
|
buffer.write("\n");
|
|
|
buffer.write("${getDeepSpace(deep)}}");
|
|
|
}
|
|
|
} else if (object is List) {
|
|
|
if (!isObject) {
|
|
|
//如果list来自某个字段,则不需要显示缩进
|
|
|
buffer.write("${getDeepSpace(deep)}");
|
|
|
}
|
|
|
buffer.write("[");
|
|
|
if (object.isEmpty) {
|
|
|
//当list为空,直接返回‘]’
|
|
|
buffer.write("]");
|
|
|
} else {
|
|
|
buffer.write("\n");
|
|
|
for (int i = 0; i < object.length; i++) {
|
|
|
buffer.write(json_print(object[i], nextDeep));
|
|
|
if (i < object.length - 1) {
|
|
|
buffer.write(",");
|
|
|
buffer.write("\n");
|
|
|
}
|
|
|
}
|
|
|
buffer.write("\n");
|
|
|
buffer.write("${getDeepSpace(deep)}]");
|
|
|
}
|
|
|
} else if (object is String) {
|
|
|
//为字符串时,需要添加双引号并返回当前内容
|
|
|
buffer.write("\"$object\"");
|
|
|
} else if (object is num || object is bool) {
|
|
|
//为数字或者布尔值时,返回当前内容
|
|
|
buffer.write(object);
|
|
|
} else {
|
|
|
//如果对象为空,则返回null字符串
|
|
|
buffer.write("null");
|
|
|
}
|
|
|
return buffer.toString();
|
|
|
}
|
|
|
|
|
|
//人脸识别和上传的图片,都需要转换为 Base64 格式的字符串提交
|
|
|
//通过图片路径将图片转换成 Base64 字符串
|
|
|
Future image2Base64(String imagePath) async {
|
|
|
File file = File(imagePath);
|
|
|
List<int> imageBytes = await file.readAsBytes();
|
|
|
String bs64 = base64Encode(imageBytes);
|
|
|
String ext = getFileExtension(imagePath);
|
|
|
print('imagePath = $imagePath, ext = $ext');
|
|
|
//String bs64Image = "data:image/png;base64," + bs64;
|
|
|
String bs64Image = "data:image/${ext};base64," + bs64;
|
|
|
return bs64Image;
|
|
|
}
|
|
|
|
|
|
//从字符路径 path 获取扩展名,不含点号
|
|
|
getFileExtension(String path) {
|
|
|
//return path.substring(path.lastIndexOf('.'));
|
|
|
//imagePath = /data/user/0/com.flutter.hyzp_ybqx04_changning/app_flutter/Pictures/flutter_test/1614662209478.jpg, ext = .jpg
|
|
|
return path.substring(path.lastIndexOf('.') + 1); //不含点号
|
|
|
}
|
|
|
|
|
|
//从字符路径 path 获取文件名(含扩展名)
|
|
|
getFileName(String path) {
|
|
|
//return path.substring(path.lastIndexOf('.'));
|
|
|
//imagePath = /data/user/0/com.flutter.hyzp_ybqx04_changning/app_flutter/Pictures/flutter_test/1614662209478.jpg, ext = .jpg
|
|
|
return path.substring(path.lastIndexOf('/') + 1); //不含点号
|
|
|
}
|
|
|
|
|
|
Widget getBtnSizeX({@required text, double width = 70.0, double height = 40.0, onPressedFun}) {
|
|
|
return Container(
|
|
|
color: Colors.white12, //onPressedFun为null时无效
|
|
|
width: width,
|
|
|
height: height,
|
|
|
child: RaisedButton(
|
|
|
padding: EdgeInsets.all(0),
|
|
|
textColor: Colors.black,
|
|
|
child: Text(text),
|
|
|
onPressed: onPressedFun,
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
//返回主页ashamp
|
|
|
// 博客园首页新随笔联系管理订阅订阅随笔 - 33 文章 - 0 评论 - 51 阅读 - 55018
|
|
|
// 在debug时使Flutter中的print打印json数据时更美观易读
|
|
|
// 为了避免deubg信息在生产环境打印,只在测试时打印,在main函数中,改变debugPrint的指向
|
|
|
//
|
|
|
// 复制代码
|
|
|
// main(){
|
|
|
// if (Api.isDebug) {
|
|
|
// debugPrint = (String message, {int wrapWidth}) {
|
|
|
// try {
|
|
|
// var object = json.decode(message);
|
|
|
// message = JsonEncoder.withIndent(' ').convert(object);
|
|
|
// } catch (e) {}
|
|
|
// printWrapped(message);
|
|
|
// };
|
|
|
// } else {
|
|
|
// debugPrint = (String message, {int wrapWidth}) {};
|
|
|
// }
|
|
|
// }
|
|
|
// 复制代码
|
|
|
// 将printWrapped方法放入工具类或你需要的地方
|
|
|
//
|
|
|
// void printWrapped(String text) {
|
|
|
// final pattern = new RegExp('.{1,800}'); // 800 is the size of each chunk
|
|
|
// pattern.allMatches(text).forEach((match) => developer.log(match.group(0)));
|
|
|
// }
|
|
|
// log方法需要引入
|
|
|
//
|
|
|
// import 'dart:developer' as developer;
|
|
|
//
|
|
|
|
|
|
//在debug时使 Flutter 中的 print 打印 json 数据时更美观易读
|
|
|
void jsonPrint(String message, {int len = 800}) {
|
|
|
//是否在生产环境
|
|
|
const bool isDebug = !const bool.fromEnvironment("dart.vm.product");
|
|
|
// if (!isDebug) {
|
|
|
// return;
|
|
|
// }
|
|
|
|
|
|
try {
|
|
|
var object = json.decode(message);
|
|
|
message = JsonEncoder.withIndent(' ').convert(object);
|
|
|
} catch (e) {
|
|
|
print('e = $e');
|
|
|
}
|
|
|
printWrapped(message);
|
|
|
}
|
|
|
|
|
|
// 打印长字符串
|
|
|
void printWrapped(String text, {int len = 800}) {
|
|
|
final pattern = RegExp('.{1,$len}'); // 800 is the size of each chunk
|
|
|
pattern.allMatches(text).forEach((match) => developer.log(match.group(0)));
|
|
|
}
|
|
|
|
|
|
//OK
|
|
|
void my_segmentPrint(String str, {int len = 800}) {
|
|
|
//是否在生产环境
|
|
|
const bool isDebug = !const bool.fromEnvironment("dart.vm.product");
|
|
|
if (!isDebug) {
|
|
|
return;
|
|
|
}
|
|
|
List list = strToList(str);
|
|
|
for (int i = 0; i < list.length; i++) {
|
|
|
print('${list[i]}');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//OK
|
|
|
List strToList(String str, {int len = 800}) {
|
|
|
List<String> strList = [];
|
|
|
if (str.length <= len) {
|
|
|
strList.add(str);
|
|
|
} else {
|
|
|
int splitCount = str.length ~/ len; //应该切割的次数
|
|
|
for (int i = 0; i < splitCount; i++) {
|
|
|
strList.add(str.substring(len * i, len * (i + 1)));
|
|
|
}
|
|
|
|
|
|
//处理最后一段
|
|
|
if (str.length % len != 0) {
|
|
|
strList.add(str.substring(len * splitCount));
|
|
|
}
|
|
|
}
|
|
|
print('strList:${strList.toString}');
|
|
|
return strList;
|
|
|
}
|
|
|
|
|
|
Widget getImageWidget() {
|
|
|
return Container(
|
|
|
alignment: Alignment(0, 0),
|
|
|
height: ScreenUtil().setHeight(346),
|
|
|
width: ScreenUtil().setWidth(942),
|
|
|
decoration: BoxDecoration(
|
|
|
image: DecorationImage(image: AssetImage('assets/images/装饰图片10.png'), fit: BoxFit.cover),
|
|
|
),
|
|
|
child: Column(
|
|
|
children: [
|
|
|
Container(
|
|
|
alignment: Alignment.centerLeft,
|
|
|
padding: EdgeInsets.only(top: ScreenUtil().setWidth(30), left: ScreenUtil().setWidth(55)),
|
|
|
child: Text('改善城市空气质量', style: TextStyle(fontSize: 17, color: Colors.white)),
|
|
|
),
|
|
|
Container(
|
|
|
alignment: Alignment.centerLeft,
|
|
|
padding: EdgeInsets.only(left: ScreenUtil().setWidth(55)),
|
|
|
child: Text('建设长江生态第一城',
|
|
|
style: TextStyle(
|
|
|
fontSize: 19,
|
|
|
color: Color.fromRGBO(49, 216, 123, 1),
|
|
|
fontWeight: FontWeight.bold)),
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
// child: Image.asset(
|
|
|
// 'assets/images/装饰图片10.png',
|
|
|
// fit: BoxFit.cover,
|
|
|
// ),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
Widget getIconBtnSizeX(
|
|
|
{@required text,
|
|
|
width = 233,
|
|
|
height = 116,
|
|
|
onTop,
|
|
|
Color color = Colors.black,
|
|
|
double circular = 10,
|
|
|
double textSize = 18}) {
|
|
|
return InkWell(
|
|
|
onTap: onTop,
|
|
|
child: Container(
|
|
|
alignment: Alignment(0, 0),
|
|
|
margin: EdgeInsets.all(0),
|
|
|
padding: EdgeInsets.all(0),
|
|
|
width: ScreenUtil().setWidth(width),
|
|
|
height: ScreenUtil().setHeight(height),
|
|
|
decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(circular)),
|
|
|
child: Row(
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
children: [
|
|
|
SizedBox(width: ScreenUtil().setWidth(12)),
|
|
|
Icon(Icons.play_arrow, color: Colors.white, size: ScreenUtil().setWidth(56)),
|
|
|
Text(
|
|
|
text,
|
|
|
style: TextStyle(color: Colors.white, fontSize: textSize),
|
|
|
)
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
}
|