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: <Widget>[
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中,增加:
<!-- 相册 -->
<key>NSPhotoLibraryUsageDescription</key>
<string>App需要您的同意,才能访问相册</string>
<!-- 相机 -->
<key>NSCameraUsageDescription</key>
<string>App需要您的同意,才能访问相机</string>
Android
在AndroidManifest.xml文件中,该文件位于<项目根目录> android/app/src/main/AndroidManifest.xml中,增加:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
image_picker具体使用:
// 声明一个list,存放image Widget
List<Widget> imageList = List();
List<String> _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();
}
}
其中,showLoading是Flutter 常用的提示框showToast、showLoading、showConfirmDialog文章中提到的共用方法。
图片显示 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: <Widget>[
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的元素
});
}
参考资料
CupertinoActionSheet组件 -- ActionSheet in Flutter
Flutter-CupertinoActionSheet的使用
【Flutter】ActionSheet, Alert, Dialog
popup: CupertinoActionSheet组件 -- Actionsheet in flutter
Image Picker plugin for Flutter
Flutter ImagePicker Plugin (No implementation found for method pickImage)
iOS关于相机相册权限设置
image_picker: (最常用场景,从相册选择或手机拍照得到照片)
No implementation found for method pickImage on channel plugins.flutter.io/image_picke
GridView
Flutter中打造多行列列表GridView组件的使用
Flutter GridView.count 及 GridView.builder
Flutter网格型布局 - GridView篇
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。