我在 Flutter 中比较新鲜。我正在尝试将图像上传到本地存储并使用 moor 将其存储到 sqflite 的路径。上传工作正常,数据也以正确的格式检索,但我仍然无法将检索的图像绑定到下面的图像预览框是父子小部件的代码:
--家长
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:moor_flutter/moor_flutter.dart';
import 'package:group_radio_button/group_radio_button.dart';
import '../dao/item.dao.dart';
import '../data/database.dart';
import '../widgets/image_picker.dart';
class EditItemScreen extends StatefulWidget {
static const routeName = '/edit-item';
@override
_EditItemScreenState createState() => _EditItemScreenState();
}
class _EditItemScreenState extends State<EditItemScreen> {
File? _pickedImage;
void _selectImage(File pickedImage) {
print("File : ${pickedImage}");
_pickedImage = pickedImage;
}
String _typeGroupValue = "Gold";
final List<String> _type = ["Gold", "Silver", "Mixed"];
final FocusScopeNode _node = FocusScopeNode();
final _nameController = TextEditingController();
final _codeController = TextEditingController();
final _typeController = TextEditingController();
final _remarkController = TextEditingController();
var itemId = 0;
var isedit = false;
final _form = GlobalKey<FormState>();
var _isInit = true;
@override
void initState() {
super.initState();
}
@override
void didChangeDependencies() async {
if (_isInit) {
if (ModalRoute.of(context)?.settings.arguments != null) {
itemId = ModalRoute.of(context)?.settings.arguments as int;
}
if (itemId != 0) {
Item editableItem = await Provider.of<ItemDao>(context, listen: false)
.getItemId(itemId);
_nameController.text = editableItem.name;
_typeGroupValue = editableItem.type;
if (editableItem.imageName != null &&
editableItem.imageName!.isNotEmpty) {
_pickedImage = File(editableItem.imageName!);
// _selectImage(_pickedImage!);
// setState(() {
if (_pickedImage != null) {
_selectImage(_pickedImage!);
CustomImagePicker(_selectImage);
}
// });
}
_codeController.text = editableItem.code;
if (editableItem.remark != null && editableItem.remark!.isNotEmpty) {
_remarkController.text = editableItem.remark!;
}
} else {}
}
_isInit = false;
super.didChangeDependencies();
}
// @override
// void didUpdateWidget(EditItemScreen oldWidget) {
// if (oldWidget._pickedImage) {}
// super.didUpdateWidget(oldWidget);
// }
@override
void dispose() {
_node.dispose();
super.dispose();
}
void _saveForm() {
FocusScope.of(context).unfocus();
_form.currentState?.save();
final database = Provider.of<ItemDao>(context, listen: false);
// Update Existing Item
if (itemId > 0) {
final newItem = ItemsCompanion(
id: Value(itemId),
name: Value(_nameController.text),
code: Value(_codeController.text),
type: Value(_typeGroupValue),
remark: Value(_remarkController.text),
imageName: Value(_pickedImage!.path),
modifiedDate: Value(DateTime.now()),
);
database.updateItem(newItem);
} else {
// Insert a New Item
final newItem = ItemsCompanion(
name: Value(_nameController.text),
code: Value(_codeController.text),
type: Value(_typeGroupValue),
remark: Value(_remarkController.text),
imageName: Value(_pickedImage!.path),
createdDate: Value(DateTime.now()),
);
database.insertItem(newItem);
}
resetAll();
Navigator.of(context).pop();
}
void resetAll() {
setState(() {
_codeController.clear();
_nameController.clear();
_typeController.clear();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Edit Item'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.save),
onPressed: _saveForm,
),
],
),
body: Padding(
padding: const EdgeInsets.all(8),
child: Form(
key: _form,
onChanged: () {},
child: ListView(
children: [
RadioGroup<String>.builder(
direction: Axis.horizontal,
groupValue: _typeGroupValue,
onChanged: (value) => setState(() {
_typeGroupValue = value.toString();
}),
items: _type,
itemBuilder: (item) => RadioButtonBuilder(
item,
),
),
TextFormField(
controller: _nameController,
decoration: const InputDecoration(
labelText: 'Item Name',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.teal)),
),
textInputAction: TextInputAction.next,
onEditingComplete: _node.nextFocus,
),
const SizedBox(
height: 10,
),
TextFormField(
controller: _codeController,
decoration: const InputDecoration(
labelText: 'Item Code',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.teal)),
),
textInputAction: TextInputAction.next,
onEditingComplete: _node.nextFocus,
),
const SizedBox(
height: 10,
),
TextFormField(
decoration: const InputDecoration(
labelText: 'Remarks',
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.teal)),
),
maxLines: 3,
textInputAction: TextInputAction.done,
controller: _remarkController,
),
const SizedBox(
height: 10,
),
CustomImagePicker(_selectImage),
],
),
),
),
);
}
}
- 孩子
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart' as syspaths;
class CustomImagePicker extends StatefulWidget {
final Function onSelectImage;
CustomImagePicker(this.onSelectImage);
@override
_CustomImagePickerState createState() => _CustomImagePickerState();
}
class _CustomImagePickerState extends State<CustomImagePicker> {
File? _storedImage;
// XFile? _pickedImage;
final ImagePicker _picker = ImagePicker();
Future<void> _takePhoto(ImageSource source) async {
final imageFile = await _picker.pickImage(
source: source,
maxWidth: 600,
);
if (imageFile == null) {
return;
}
setState(() {
_storedImage = File(imageFile.path);
});
final appDir = await syspaths.getApplicationDocumentsDirectory();
final fileName = path.basename(imageFile.path);
final savedImage =
await File(imageFile.path).copy('${appDir.path}/$fileName');
widget.onSelectImage(savedImage);
}
var _isInit = true;
@override
void initState() {
super.initState();
}
// @override
// void didChangeDependencies() async {
// if (_isInit) {
// widget.onSelectImage();
// } else {}
// }
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Container(
width: 150,
height: 100,
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.grey),
),
child: _storedImage != null
? Image.file(
_storedImage!,
fit: BoxFit.cover,
width: double.infinity,
)
: const Text(
'No Image Taken',
textAlign: TextAlign.center,
),
alignment: Alignment.center,
),
const SizedBox(
height: 10,
),
Expanded(
child: TextButton.icon(
onPressed: () {
showModalBottomSheet(
context: context,
builder: ((builder) => bottomSheet()),
);
},
icon: const Icon(Icons.camera),
label: const Text('Take Picture'),
),
),
],
);
}
Widget bottomSheet() {
return Container(
height: 100.0,
width: MediaQuery.of(context).size.width * 1,
margin: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 20,
),
child: Column(
children: <Widget>[
const Text(
"Choose an Image of Item.",
style: TextStyle(
fontSize: 20,
),
),
const SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton.icon(
onPressed: () async {
Navigator.of(context).pop();
await _takePhoto(ImageSource.camera);
},
icon: const Icon(Icons.camera),
label: const Text('Camara'),
),
TextButton.icon(
onPressed: () async {
Navigator.of(context).pop();
await _takePhoto(ImageSource.gallery);
},
icon: const Icon(Icons.image),
label: const Text('Gallary'),
)
],
)
],
),
);
}
}