I would like to create a page in a flutter app where the user can use a multi-image picker as many times as they want to create different sets of named photos. In essence, each time the user clicks on a Container with an InkWell, the select photos pop-up appears. The user selects their photos. The photos then appear in a new column widget with a text field where they can name their selection. The user can then continue to click on the Container with Inkwell to keep adding more column widgets with different selections of photos.
I created a page where a Column widget is created every time the user clicks on a Container with Inkwell (using the Inkwell's onTap functionality). Within the Column I will have a TextField where the user can name the selection and the MultiImagePickerView.
Currently when I click on my InkWell Container, the photo selection pop-up comes up and I can select photos. But when I hit 'add', the app hangs.
I was expecting a new Column to appear on my page with the selected photos inside.
import 'package:flutter/material.dart';
import 'package:multi_image_picker_view/multi_image_picker_view.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(const MyApp());
}
// a dynamic page which adds widgets by push of inkwell area
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
//creating the column where the list of widgets is going to go
//one widget per move being tracked
List<Widget> widgetList = [];
Column col = Column(
children: [],
);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
col,
initialWidget(),
],
),
),
);
}
void addWidget() {
setState(() {
widgetList.add(otherWidget());
col = Column(
children: widgetList,
);
});
}
initialWidget() {
return Container(
//margin: margin ?? pickerView.padding,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4), //color: Colors.blueGrey
//Theme.of(context).colorScheme.secondary.withOpacity(0.05),
),
height: 160,
clipBehavior: Clip.hardEdge,
width: double.infinity,
child: InkWell(
borderRadius: BorderRadius.circular(4),
onTap: addWidget, //pickerView.controller.pickImages,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add_photo_alternate_outlined,
size: 30, color: Theme.of(context).primaryColor),
const SizedBox(height: 4),
Text('Add a move to track',
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.w400,
fontSize: 14))
],
),
),
),
);
}
}
Future<List<ImageFile>> pickImagesUsingImagePicker(bool allowMultiple) async {
final picker = ImagePicker();
final List<XFile> xFiles;
if (allowMultiple) {
xFiles = await picker.pickMultiImage(maxWidth: 1080, maxHeight: 1080);
} else {
xFiles = [];
final xFile = await picker.pickImage(
source: ImageSource.gallery, maxHeight: 1080, maxWidth: 1080);
if (xFile != null) {
xFiles.add(xFile);
}
}
if (xFiles.isNotEmpty) {
return xFiles.map<ImageFile>((e) => convertXFileToImageFile(e)).toList();
}
return [];
}
class otherWidget extends StatefulWidget {
const otherWidget({super.key});
@override
State<otherWidget> createState() => _otherWidget();
}
class _otherWidget extends State<otherWidget> {
//defining the controller which contains all the images the user has selected
//may need to be reset? or one per widget?
final controller = MultiImagePickerController(
maxImages: 10,
picker: (allowMultiple) async {
return await pickImagesUsingImagePicker(allowMultiple);
});
@override
Widget build(BuildContext context) {
controller.pickImages(); //maybe this is in the wrong place? but still needs to be in this class
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//TextField(
// decoration: InputDecoration(
// border: OutlineInputBorder(),
// hintText: 'Enter name of move',
// ),
//),
//Text('where photos go'),
MultiImagePickerView(
controller: controller,
builder: (context, imageFile) {
return DefaultDraggableItemWidget(
imageFile: imageFile,
boxDecoration:
BoxDecoration(borderRadius: BorderRadius.circular(20)),
closeButtonAlignment: Alignment.topLeft,
fit: BoxFit.cover,
closeButtonIcon:
const Icon(Icons.delete_rounded, color: Colors.red),
closeButtonBoxDecoration: null,
showCloseButton: true,
closeButtonMargin: const EdgeInsets.all(3),
closeButtonPadding: const EdgeInsets.all(3),
);
},
initialWidget: null,
addMoreButton: DefaultAddMoreWidget(
icon: Icon(Icons.image_search_outlined,
color: Theme.of(context).colorScheme.secondary),
),
),
],
);
}
}