1.Flutter项目上传图片(例如更改头像)
1)安装依赖包
这个依赖包可以在官网上获取:地址
image_picker: ^0.6.7+17
2)引入文件
import 'package:image_picker/image_picker.dart';
import 'dart:io';
3)选取图片【在需要上传图片的点击事件中使用这个方法】
File _image;
final picker = ImagePicker();
Future getImage() async {
var pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
_image = File(pickedFile.path);
if (pickedFile != null) {
//在这里可以写后端给的接口进行图片上传
}
else {
print('No image selected.');
}
});
}
小提示:将图片文件数据发送到后端的时候需要注意后端接收的是什么类型的数据
如果是文件MultipartFile类型的那么可以这样写:
upLoadImage(File image) async {
String path = image.path;
var name = path.substring(path.lastIndexOf("/") + 1, path.length);
FormData formData =FormData.fromMap({
"file": await MultipartFile.fromFile(path, filename: name)
});
Map response =await getDynamicData(
UrlConfig.user,"/api/user/upload","post",formData: formData);
return response;
}
如果是字符串类型的,那就说明后端还有另外的一个接口上传图片到云服务器上面后前端会获得一个图片的地址,那么这个时候我们就只需要把这个字符串类型的地址传给后端就可以了。
4)在组件中使用这个方法
SizedBox(
width: 200.0,
height: 100.0,
child: FloatingActionButton(
elevation:0,
backgroundColor:Color(0xE6E6E6E6),
onPressed: getImage,
tooltip: 'Pick Image',
child: _image == null? Image.asset(
"assets/user/huzhao_pass.png",
) : Image.file(_image),
),
),
2.Flutter项目时间格式化
描述:Flutter版本的时间处理(多少天前,多少小时前,多少分钟前,多少秒前)
例如:
获取到的时间 | 当前时间 |
2020-12-21 15:30:30 | 2020-12-24 15:30:30 |
那么页面上将显示3天前。
以下是代码:
getnoticeTime(str){
if(str!='' ){
var arr = str.split(" ");
if(this.isToday(arr[0])){
DateTime d = DateTime.now();
var h = d.hour;
var m = d.minute;
var s = d.second;
var hour = arr[1].split(':');
if(h-hour[0]>1){
return (h-hour[0]).toString()+"小时前";
}
else {
if(m-hour[1]>=1){
return (h-hour[0]).toString()+"分钟前";
}
else{
return (s-hour[2]).toString()+"秒前";
}
}
}
else {
var d = DateTime.now();
var time = d.toString().split(' ')[0];
var daynum = this.DateDiff(time,arr[0]);
return (daynum).toString()+"天前";
}
}
}
// 判断两个时间相差多少天,此处需要注意的是difference这个方法只能传入时间格式的参数进行比较,所以前面需要一步转换的过程
DateDiff(sDate1, sDate2) { //sDate1和sDate2是yyyy-MM-dd格式
var time = DateTime.parse(sDate1);
var time2 = DateTime.parse(sDate2);
var time3 = time.difference(time2).inDays;
return time3; //返回相差天数
}
//判断是不是今天
isToday(str){
var d = DateTime.now();
return str == (d.toString().split(' ')[0]);
}
3.Flutter中将组件生成图片保存到手机相册。
1)安装依赖包(在pubspec.yaml文件添加插件)
image_gallery_saver安装1.5.0版本
# 权限控制插件
permission_handler: 5.0.1
permission_handler_platform_interface: ^2.0.1
# 文件保存插件
image_gallery_saver: 1.5.0
添加以上代码以后需要安装哦
flutter pub get
2)android和ios配置
(1)ios 修改文件【在ios/Runner/Info.plist添加以下代码】
<key>NSPhotoLibraryUsageDescription</key>
<string></string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>请允许APP保存图片到相册</string>
(2)android 修改文件【在android/app/src/main/AndroidManifest.xml添加以下代码】
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
3)将需要生成图片的组件用RepaintBoundary包裹
GlobalKey globalKey = GlobalKey();
RepaintBoundary(
key: globalKey,
child:Text('我要生成图片'),
)
4)保存图片到相册【再点击事件中调用下面这个方法】
/// 保存图片
static Future<void> saveImage(GlobalKey globalKey) async {
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
var image = await boundary.toImage(pixelRatio: 6.0);
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
// final result = await ImageGallerySaver.saveImage(pngBytes,
// quality: 60, name: "hello");
// if (result) {
// print('ok');
// // toast("保存成功", wring: false);
// } else {
// print('error');
// }
if (Platform.isIOS) {
var status = await Permission.photos.status;
if (status.isUndetermined) {
Map<Permission, PermissionStatus> statuses = await [
Permission.photos,
].request();
saveImage(globalKey);
}
if (status.isGranted) {
final result = await ImageGallerySaver.saveImage(pngBytes,
quality: 60, name: "hello");
if (result) {
print('ok');
// toast("保存成功", wring: false);
} else {
print('error');
// toast("保存失败");
}
}
if (status.isDenied) {
print("IOS拒绝");
}
} else if (Platform.isAndroid) {
var status = await Permission.storage.status;
if (status.isUndetermined) {
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
].request();
saveImage(globalKey);
}
if (status.isGranted) {
print("Android已授权");
final result = await ImageGallerySaver.saveImage(pngBytes, quality: 60);
if (result != null) {
print('ok');
// toast("保存成功", wring: false);
} else {
print('error');
// toast("保存失败");
}
}
if (status.isDenied) {
print("Android拒绝");
}
}
}
5)完整的保存图片的文件
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:interviewer_app/common/component_index.dart';
// 一定要引入这三个插件
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter/services.dart';
import 'dart:ui' as ui;
import 'dart:typed_data';
import 'dart:io';
class ShareJob extends StatefulWidget {
const ShareJob({Key key, this.searchKey}) : super(key: key);
final String searchKey;
@override
State<StatefulWidget> createState() {
return new _ShareJobState();
}
}
class _ShareJobState extends State<ShareJob> {
// globalKey 在这里设置
GlobalKey globalKey = GlobalKey();
Uint8List newPngBytes;
Widget shareImage() {
return
RepaintBoundary(
key: globalKey,
child:
Container(
child:
// 图片
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xFF5B9AFF),
boxShadow:[
BoxShadow(
color: Color(0x1A000000),
offset: Offset(0, 5.0),
blurRadius: 24.0
),
]),
width: MediaQuery.of(context).size.width * 0.6,
child:
Column(
children: [
Gaps.vGap25,
Text('热招职位', style: TextStyle(fontSize: 22, color: Colors.white, fontWeight: FontWeight.w300),),
Gaps.vGap25,
Container(
margin: EdgeInsets.only(bottom: 22,left: 15,right: 15),
// padding: EdgeInsets.only(bottom: 22,left: 15,right: 15),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10.0),
boxShadow:[
BoxShadow(
color: Color(0x1A000000),
offset: Offset(0, 5.0),
blurRadius: 24.0
),
]),
// padding: EdgeInsets.all(10),
// margin: EdgeInsets.only(bottom: 6),
// width: MediaQuery.of(context).size.width * 0.6,
// height: 305,
child: Column(
children: [
Gaps.vGap25,
Gaps.vGap10,
Text('测试工程师', style: TextStyle(fontSize: 15, color: Color(0xFF313753), fontWeight: FontWeight.w500),),
Gaps.vGap10,
Text('15k-20K | 上海', style: TextStyle(fontSize: 15, color: Color(0xFFF4A25A), fontWeight: FontWeight.w500),),
Gaps.vGap10,
Text('公司名', style: TextStyle(fontSize: 10, color: Color(0xFF313753), fontWeight: FontWeight.w400),),
Gaps.vGap15,
Image.asset(Utils.getImgPath('checked'),
width: 115.0),
Gaps.vGap25,
Text('长按查看职位详情', style: TextStyle(fontSize: 9, color: Color(0xFF313753), fontWeight: FontWeight.w400),),
Gaps.vGap25,
],
),
),
],
),
),
],
),
)
);
}
/// 保存图片
static Future<void> saveImage(GlobalKey globalKey) async {
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
var image = await boundary.toImage(pixelRatio: 6.0);
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
// final result = await ImageGallerySaver.saveImage(pngBytes,
// quality: 60, name: "hello");
// if (result) {
// print('ok');
// // toast("保存成功", wring: false);
// } else {
// print('error');
// }
if (Platform.isIOS) {
var status = await Permission.photos.status;
if (status.isUndetermined) {
Map<Permission, PermissionStatus> statuses = await [
Permission.photos,
].request();
saveImage(globalKey);
}
if (status.isGranted) {
final result = await ImageGallerySaver.saveImage(pngBytes,
quality: 60, name: "hello");
if (result) {
print('ok');
// toast("保存成功", wring: false);
} else {
print('error');
// toast("保存失败");
}
}
if (status.isDenied) {
print("IOS拒绝");
}
} else if (Platform.isAndroid) {
var status = await Permission.storage.status;
if (status.isUndetermined) {
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
].request();
saveImage(globalKey);
}
if (status.isGranted) {
print("Android已授权");
final result = await ImageGallerySaver.saveImage(pngBytes, quality: 60);
if (result != null) {
print('ok');
// toast("保存成功", wring: false);
} else {
print('error');
// toast("保存失败");
}
}
if (status.isDenied) {
print("Android拒绝");
}
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(title: Text('分享职位'), titleSpacing: 0, centerTitle: true),
body: SingleChildScrollView(
child: Container(
child: Column(children: [
Gaps.vGap25,
Row(
children: [
// http://images.shejidaren.com/wp-content/uploads/2020/03/36365-4.png
// IconButton(
// iconSize: 22,
// icon: const Icon(Icons.close),
// onPressed: (){
// },
// )
Gaps.hGap30,
Gaps.hGap10,
Gaps.hGap10,
Column(
children: [
Container(
decoration: new BoxDecoration(
color: Cor.roundbg_1,
borderRadius: BorderRadius.circular(100),
),
padding: EdgeInsets.all(10),
margin: EdgeInsets.only(bottom: 6),
width: 60,
height: 60,
child: Image.network(
'http://images.shejidaren.com/wp-content/uploads/2020/03/36365-4.png'),
),
Text(
'微信好友',
textAlign: TextAlign.center,
style: TextStyle(color: Cor.black_1, fontSize: 14),
)
],
),
Gaps.hGap30,
Gaps.hGap10,
Gaps.hGap10,
Column(
children: [
Container(
decoration: new BoxDecoration(
color: Cor.roundbg_1,
borderRadius: BorderRadius.circular(100),
),
padding: EdgeInsets.all(10),
margin: EdgeInsets.only(bottom: 6),
width: 60,
height: 60,
child: Image.network(
'https://www.sj520.cn/sc/ima/weixin_sj520_11.jpg'),
),
Text(
'朋友圈',
textAlign: TextAlign.center,
style: TextStyle(color: Cor.black_1, fontSize: 14),
)
],
),
],
),
Gaps.vGap20,
// 灰色横线
Container(
decoration: new BoxDecoration(color: Cor.roundbg_1),
width: double.infinity,
height: 10,
),
Gaps.vGap15,
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
'已生成朋友圈图片',
textAlign: TextAlign.center,
style: TextStyle(color: Cor.black_1.withOpacity(0.65), fontSize: 14),
),
],
),
Gaps.vGap15,
shareImage(),
Gaps.vGap15,
Gaps.vGap10,
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
RaisedButton(
color: Cor.blue_1,
highlightColor: Colors.blue[100],
colorBrightness: Brightness.dark,
splashColor: Cor.blue_2,
padding: EdgeInsets.only(left: 34,right: 34),
child: Text(
"保存至相册",
style: TextStyle(color: Colors.white, fontSize: 14),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)),
onPressed: () async {
print('------');
print(globalKey.currentContext);
// createImageFromRepaintBoundary(globalKey);
// final g = createImageFromWidget(saveImage());
// print(g);
saveImage(globalKey);
},
),
],
),
Gaps.vGap25,
Gaps.vGap25,
]),
),
),
);
}
}