I'm using a stateless screen which contains two stateful widgets, an imagepicker and a form with many fields. When i open the keyboard, if i selected an image previously, it disappears and the entire imagepicker widget is reinitialized.
This means that the only way to submit an image is select it when the keyboard is closed and never reopen it. I already tried setting a key and with other solutions i found here, but nothing works. I can't fully understand this behavior, and of course i need the image to stay there even if i open and close the keyboard.
A fast solution could be simply move the imagepicker in the form itself, but i'd prefer to keep them in different widgets. I really need to understand what i'm missing.
Main page:
class ProductAddScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final GlobalKey<ProductAddUpdateFormState> _keyForm = GlobalKey();
final GlobalKey<ImageInputProductState> _keyImage = GlobalKey();
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: MediaQuery.of(context).padding.top,
),
TitleHeadline(
title: 'Add',
backBtn: true,
trailingBtn: Icons.info,
trailingBtnAction: () =>
Navigator.of(context, rootNavigator: true).push(
MaterialPageRoute(builder: (context) => InfoScreen()),
),
),
const SizedBox(height: 8),
ImageInputProduct(key: _keyImage),
ProductAddUpdateForm(key: _keyForm),
const SizedBox(height: 16),
ButtonWide(
action: () => _keyForm.currentState.submit(
screenContext: context,
newImage: _keyImage.currentState.storedImage),
text: 'Confirm',
),
],
),
),
);
}
}
Imagepicker:
class ImageInputProduct extends StatefulWidget {
final String preImage;
ImageInputProduct({Key key, this.preImage = ''}) : super(key: key);
@override
ImageInputProductState createState() => ImageInputProductState();
}
class ImageInputProductState extends State<ImageInputProduct> {
File _storedImage;
// Get the selected file
File get storedImage {
return _storedImage;
}
// Take an image from camera
Future<void> _takePicture() async {
final picker = ImagePicker();
final imageFile = await picker.getImage(
source: ImageSource.camera,
maxHeight: 1280,
maxWidth: 1280,
);
setState(() {
_storedImage = File(imageFile.path);
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
height: 130,
width: 200,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(
width: 1,
color: Colors.black12,
),
),
child: _storedImage == null
? widget.preImage.isEmpty
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.image,
color:
Theme.of(context).primaryColor.withOpacity(0.4),
size: 48,
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 4,
),
child: Text(
'No image selected',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyText2,
),
)
],
)
: ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(8),
topLeft: Radius.circular(8),
bottomRight: Radius.circular(8),
topRight: Radius.circular(8),
),
child: Image.network(
widget.preImage,
fit: BoxFit.cover,
width: double.infinity,
),
)
: ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(8),
topLeft: Radius.circular(8),
bottomRight: Radius.circular(8),
topRight: Radius.circular(8),
),
child: Image.file(
_storedImage,
fit: BoxFit.cover,
width: double.infinity,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 48, vertical: 8),
child: ButtonWideOutlined(
action: _takePicture,
text: 'Select image',
),
),
],
);
}
}
The form is just a standard form, and this question is already too long. I'd really appreciate any suggestion. The only thing i know is that initState is called in the imagepicker every time i open the keyboard (and therefore the form state changes).