android 菜单默认显示图片,Flutter 实现ActionSheet底部弹出菜单操作表:打开相机或相册上传图片后GridView网格布局显示图片...

CupertinoActionSheet组件 -- ActionSheet in Flutter

在开发中,ActionSheet也是比较常用的控件,Flutter里面也提供了相应的控件CupertinoActionSheet。

CupertinoActionSheet组件 -- ActionSheet in Flutter

CupertinoActionSheet具体使用

import 'package:flutter/material.dart';

import 'package:flutter/cupertino.dart';

import 'package:app/common/toast.dart';

// 从底部弹出CupertinoActionSheet使用showCupertinoModalPopup

void _handleTap() { // 某个GestureDetector的事件

if (operateType == 'add' || operateType == 'Edit') {

showCupertinoModalPopup(

context: context,

builder: (BuildContext context) => actionSheet(),

).then((value) {});

}

}

// 底部弹出菜单actionSheet

Widget actionSheet() {

return new CupertinoActionSheet(

title: new Text(

'菜单',

style: descriptiveTextStyle,

),

actions: [

CupertinoActionSheetAction(

child: const Text(

'打开相机拍照',

style: TextStyle(

fontSize: 14.0,

fontFamily: 'PingFangRegular',

),

),

onPressed: () {

// 打开相机拍照

_getCameraImage();

// 关闭菜单

Navigator.of(context).pop();

},

),

CupertinoActionSheetAction(

child: const Text(

'打开相册,选取照片',

style: TextStyle(

fontSize: 14.0,

fontFamily: 'PingFangRegular',

),

),

onPressed: () {

// 打开相册,选取照片

_getGalleryImage();

// 关闭菜单

Navigator.of(context).pop();

},

)

],

cancelButton: CupertinoActionSheetAction(

child: new Text(

'取消',

style: TextStyle(

fontSize: 13.0,

fontFamily: 'PingFangRegular',

color: const Color(0xFF666666),

),

),

onPressed: () {

// 关闭菜单

Navigator.of(context).pop();

},

),

);

}

image_picker 使用相机或相册

在pubspec.yaml文件里添加:

image\_picker : ^lastest\_version

image_picker,一个适用于iOS和Android的Flutter插件,用于从图像库中获取图像和使用相机拍摄新照片。

配置访问相机、相册权限

iOS

在Info.plist文件中,该文件位于 /ios/Runner/Info.plist中,增加:

NSPhotoLibraryUsageDescription

App需要您的同意,才能访问相册

NSCameraUsageDescription

App需要您的同意,才能访问相机

Android

在AndroidManifest.xml文件中,该文件位于 android/app/src/main/AndroidManifest.xml中,增加:

image_picker具体使用:

// 声明一个list,存放image Widget

List imageList = List();

List _imgUrls = []; // 存放图片路径

File _cameraImage;

File _galleryImage;

Future _getCameraImage() async {

print('调用了: 打开相机');

var image = await ImagePicker.pickImage(source: ImageSource.camera); // 使用相机

setState(() {

_cameraImage = image;

print('_cameraImage: ' + _cameraImage.toString());

_uploadPic(_cameraImage);

});

}

Future _getGalleryImage() async {

print('调用了: 打开相册');

var image =

await ImagePicker.pickImage(source: ImageSource.gallery); // 使用图库

setState(() {

_galleryImage = image;

print('_galleryImage: ' + _galleryImage.toString());

_uploadPic(_galleryImage);

});

}

// 上传图片

void _uploadPic(File imgfile) async {

showLoading(context, '上传中,请等待......');

try {

String path = imgfile.path;

// print('Image path: ' + path);

var str = path.split('-');

var filename = str[str.length - 1];

String uploadServer = BaseUrl.uploadServer;

FormData formData = FormData.fromMap({

"file": await MultipartFile.fromFile(path, filename: filename),

});

Response response = await dio.post(uploadServer, data: formData);

// print(response);

setState(() {

dynamic rtn = jsonDecode(response.toString()); // 解析接口返回的json数据

// print(rtn);

String imgUrl = rtn['data'];

_imgUrls.add(imgUrl);

// print(" _imgUrls:" + _imgUrls.toString());

var isUrl = imgUrl.startsWith('http');

if (!isUrl) {

imgUrl = BaseUrl.url + imgUrl;

}

imageList

..add(Image.network(

imgUrl,

height: 50,

width: 50,

fit: BoxFit.fitWidth, // 显示可能拉伸,可能裁剪,宽度充满

));

// print(" imageList:" + imageList.toString());

});

} on DioError catch (e) {

//catch 提示

print('catch 提示: ' + e.toString());

if (e.response != null) {

print(e.response.data);

} else {

showToast("数据加载失败");

print(e.request);

print(e.message);

}

} finally {

// 隐藏loading框

Navigator.of(context).pop();

}

}

图片显示 GridView

Widget _buildGridViewList() {

return new Container(

width: MediaQuery.of(context).size.width - 40,

color: const Color(0xFFFFFFFF),

padding: EdgeInsets.only(left: 8.0),

child: GridView.builder(

shrinkWrap: true, //是否根据子widget的总长度来设置GridView的长度,默认值为false

gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(

mainAxisSpacing: 3,

crossAxisSpacing: 3,

crossAxisCount: 3, //每行三列

childAspectRatio: 1.0, //显示区域宽高相等

),

itemCount: imageList.length,

itemBuilder: (context, index) {

// print("调用了 imageList[" + index.toString() + "]" + imageList[index].toString());

return new Stack(

// 堆叠组件

children: [

Container(

alignment: Alignment.center,

height: 54,

// width: 54.0,

color: const Color(0xFFFFFFFF),

padding: EdgeInsets.only(left: 8.0),

child: imageList[index],

),

Container(

height: 54,

// width: 54.0,

padding: new EdgeInsets.fromLTRB(0, 10, 0, 0),

alignment: Alignment.bottomRight,

child: GestureDetector(

onTap: () => _handleTapDelePic(index),

child: Padding(

padding: const EdgeInsets.only(right: 5),

child: new Text('删除'),

),

),

),

],

);

},

),

);

}

void _handleTapDelePic(int index) {

// print('点击删除 ' + index.toString());

setState(() {

imageList.removeAt(index); //删除位置为index的元素

_imgUrls.removeAt(index); //删除位置为index的元素

});

}

参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值