我正在尝试将库image_picker和image_cropper实现到旧代码,但是它扩展了无状态小部件。
import 'package:elxr_mobile/components/export.dart';
import 'package:elxr_mobile/models/export.dart';
import 'package:elxr_mobile/pages/04_profile/export.dart';
import 'package:elxr_mobile/styles/export.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
class ProfileHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, ElxrViewModel>(
converter: ElxrViewModel.fromStore,
builder: (BuildContext context, vm) {
return Container(
child: Column(
children: <Widget>[
InkWell(
child: CircleAvatar(
radius: 30.0,
backgroundImage:
AssetImage('assets/images/profile.icon.round.png'),
backgroundColor: Colors.white,
),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => AboutMePage()),
);
},
),
Container(height: 5.0),
Text(
vm.user?.displayName ?? "",
textAlign: TextAlign.center,
style: ProfileTextTheme.header(),
),
Container(height: 5.0),
Container(
width: 150.0,
padding: EdgeInsets.fromLTRB(20.0, 5.0, 20.0, 5.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
)),
child: Text(
'KIT: ${(vm.customer?.userKitNo ?? "").padLeft(8, '0')}',
textAlign: TextAlign.center,
style: ProfileTextTheme.subtext(context),
),
),
Container(height: 5.0),
],
),
);
});
}
}
当我单击用户头像时,它应该显示从画廊中选择图片或从相机拍摄图片的选项,然后用户可以裁剪该图片。
当前用户界面显示在下图中。 请帮忙!
答案 0 :(得分:0)
这是在没有选择器的情况下可以执行的操作,您可以在其中选择要从中导入图像的来源。必须有一个插件,否则您可以自己创建对话框。
InkWell(
child: CircleAvatar(
radius: 30.0,
backgroundImage:
AssetImage('assets/images/profile.icon.round.png'),
backgroundColor: Colors.white,
),
onTap: () async {
File file = await ImagePicker.pickImage(source: ImageSource.gallery);
if (file == null) {return;}
File croppedFile = await ImageCropper.cropImage(
sourcePath: file.path,
ratioX: 1.0,
ratioY: 1.0,
maxWidth: 512,
maxHeight: 512,
circleShape: true);
if (croppedFile == null) {return;}
Directory directory = await getApplicationDocumentsDirectory();
String finalPath = directory.path + '/profile_picture' + pathPlugin.extension(croppedFile.path);
File finalImage = await croppedFile.copy(finalPath);
imageCache.clear();
},
),
答案 1 :(得分:-1)
我通过更改类以扩展StatefulWidget并创建处理程序和对话框来解决此问题。
profile_header.dart:
import 'dart:io';
import 'package:elxr_mobile/components/export.dart';
import 'package:elxr_mobile/models/export.dart';
import 'package:elxr_mobile/helpers/image_picker_handler.dart';
import 'package:elxr_mobile/styles/export.dart';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
class ProfileHeader extends StatefulWidget {
ProfileHeader({Key key, this.title}) : super(key: key);
final String title;
@override
_ProfileHeaderState createState() => new _ProfileHeaderState();
}
class _ProfileHeaderState extends State<ProfileHeader>
with TickerProviderStateMixin, ImagePickerListener {
File _image;
AnimationController _controller;
ImagePickerHandler imagePicker;
@override
void initState() {
super.initState();
_controller = new AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
);
imagePicker = new ImagePickerHandler(this, _controller);
imagePicker.init();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, ElxrViewModel>(
converter: ElxrViewModel.fromStore,
builder: (BuildContext context, vm) {
return Container(
child: Column(
children: <Widget>[
InkWell(
child: _image == null
? CircleAvatar(
radius: 30.0,
backgroundColor: Colors.white,
backgroundImage: AssetImage(
"assets/images/profile.icon.round.png"))
: CircleAvatar(
radius: 30.0,
backgroundColor: Colors.white,
backgroundImage: ExactAssetImage(_image.path)),
onTap: () => imagePicker.showDialog(context),
),
Container(height: 5.0),
Text(
vm.user?.displayName ?? "",
textAlign: TextAlign.center,
style: ProfileTextTheme.header(),
),
Container(height: 5.0),
Container(
width: 150.0,
padding: EdgeInsets.fromLTRB(20.0, 5.0, 20.0, 5.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
)),
child: Text(
'KIT: ${(vm.customer?.userKitNo ?? "").padLeft(8, '0')}',
textAlign: TextAlign.center,
style: ProfileTextTheme.subtext(context),
),
),
Container(height: 5.0),
],
),
);
});
}
@override
userImage(File _image) {
setState(() {
this._image = _image;
});
}
}
image_picker_handler.dart:
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:elxr_mobile/helpers/image_picker_dialog.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
class ImagePickerHandler {
ImagePickerDialog imagePicker;
AnimationController _controller;
ImagePickerListener _listener;
ImagePickerHandler(this._listener, this._controller);
openCamera() async {
imagePicker.dismissDialog();
var image = await ImagePicker.pickImage(source: ImageSource.camera);
cropImage(image);
}
openGallery() async {
imagePicker.dismissDialog();
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
cropImage(image);
}
void init() {
imagePicker = new ImagePickerDialog(this, _controller);
imagePicker.initState();
}
Future cropImage(File image) async {
File croppedFile = await ImageCropper.cropImage(
sourcePath: image.path,
ratioX: 1.0,
ratioY: 1.0,
maxWidth: 512,
maxHeight: 512,
);
_listener.userImage(croppedFile);
}
showDialog(BuildContext context) {
imagePicker.getImage(context);
}
Future<void> retrieveLostData() async {
final LostDataResponse response = await ImagePicker.retrieveLostData();
if (response == null) {
return;
}
if (response.file != null) {
if (response.type == RetrieveType.video) {
return;
} else {
_listener.userImage(response.file);
}
} else {
return;
}
}
}
abstract class ImagePickerListener {
userImage(File _image);
}
image_picker_dialog.dart:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:elxr_mobile/helpers/image_picker_handler.dart';
// ignore: must_be_immutable
class ImagePickerDialog extends StatelessWidget {
ImagePickerHandler _listener;
AnimationController _controller;
BuildContext context;
ImagePickerDialog(this._listener, this._controller);
Animation<double> _drawerContentsOpacity;
Animation<Offset> _drawerDetailsPosition;
void initState() {
_drawerContentsOpacity = new CurvedAnimation(
parent: new ReverseAnimation(_controller),
curve: Curves.fastOutSlowIn,
);
_drawerDetailsPosition = new Tween<Offset>(
begin: const Offset(0.0, 1.0),
end: Offset.zero,
).animate(new CurvedAnimation(
parent: _controller,
curve: Curves.fastOutSlowIn,
));
}
getImage(BuildContext context) {
if (_controller == null ||
_drawerDetailsPosition == null ||
_drawerContentsOpacity == null) {
return;
}
_controller.forward();
showDialog(
context: context,
builder: (BuildContext context) => new SlideTransition(
position: _drawerDetailsPosition,
child: new FadeTransition(
opacity: new ReverseAnimation(_drawerContentsOpacity),
child: this,
),
),
);
}
void dispose() {
_controller.dispose();
}
startTime() async {
var _duration = new Duration(milliseconds: 200);
return new Timer(_duration, navigationPage);
}
void navigationPage() {
Navigator.pop(context);
}
dismissDialog() {
_controller.reverse();
startTime();
}
@override
Widget build(BuildContext context) {
this.context = context;
return new Material(
type: MaterialType.transparency,
child: new Opacity(
opacity: 1.0,
child: new Container(
padding: EdgeInsets.fromLTRB(30.0, 0.0, 30.0, 20.0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new GestureDetector(
onTap: () => _listener.openCamera(),
child: roundedButton(
"Camera",
EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
const Color(0xFF167F67),
const Color(0xFFFFFFFF)),
),
new GestureDetector(
onTap: () => _listener.openGallery(),
child: roundedButton(
"Gallery",
EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
const Color(0xFF167F67),
const Color(0xFFFFFFFF)),
),
const SizedBox(height: 15.0),
new GestureDetector(
onTap: () => dismissDialog(),
child: new Padding(
padding: EdgeInsets.fromLTRB(30.0, 0.0, 30.0, 0.0),
child: roundedButton(
"Cancel",
EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
Colors.redAccent,
const Color(0xFFFFFFFF)),
),
),
],
),
),
));
}
Widget roundedButton(
String buttonLabel, EdgeInsets margin, Color bgColor, Color textColor) {
return new Container(
margin: margin,
padding: EdgeInsets.all(10.0),
alignment: FractionalOffset.center,
decoration: new BoxDecoration(
color: bgColor,
borderRadius: new BorderRadius.all(const Radius.circular(10.0)),
),
child: Text(
buttonLabel,
style: new TextStyle(
color: textColor,
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontFamily: "Cairo"),
),
);
}
}