Package multiple_image_camera on pub.dev has some limitations so I'm trying to create my own component that can be customized. I tried placing the imagesFromCameraRoll.add(img) inside and outside setState. Also tried to put takePicture contents into the onPressed event, did not work.
Future<void> openCamera(BuildContext context) async {
await startCamera(0); // rear
if (!mounted) return;
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Scaffold(
appBar: AppBar(title: const Text('Fotos')),
body: Stack(
children: [
SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: FittedBox(
fit: BoxFit.cover,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width / cameraController.value.aspectRatio,
child: CameraPreview(cameraController),
),
),
),
imagesFromCameraRoll.isNotEmpty
? SafeArea(
child: Align(
alignment: Alignment.bottomLeft,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 150),
child: Container(
height: 100,
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8.0)),
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: imagesFromCameraRoll.length,
itemBuilder: (context, index) {
return ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.file(
File(imagesFromCameraRoll[index].path),
height: 90,
fit: BoxFit.cover,
),
);
},
),
),
),
),
],
),
),
)
: Container(),
],
),
floatingActionButton: FloatingActionButton.large(
onPressed: () async {
takePicture();
},
child: const Icon(Icons.camera_alt),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
),
),
);
}
List<XFile> imagesFromCameraRoll = [];
void takePicture() async {
if (cameraController.value.isTakingPicture || !cameraController.value.isInitialized) {
return;
}
try {
final XFile img = await cameraController.takePicture();
setState(() {
imagesFromCameraRoll.add(img);
});
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}
any help would be really appreciated. thanks
The navigator push method is called imperatively when you call openCamera
, so the widget returned by the MaterialPageRoute
's builder method won't be reactive to the state changes of the current StatefulWidget
state.
You should extract the Scaffold
to its own StatefulWidget
and manage the states (such as imagesFromCameraRoll
) inside this new StatefulWidget
state. Move methods that modify those states to this new widget as well.
Future<void> openCamera(BuildContext context) async {
await startCamera(0); // rear
if (!mounted) return;
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => FotosScreen(),
),
);
}
class FotosScreen extends StatefulWidget {
const FotosScreen({super.key});
@override
State<FotosScreen> createState() => _FotosScreenState();
}
class _FotosScreenState extends State<FotosScreen> {
List<XFile> imagesFromCameraRoll = [];
void takePicture() async {
if (cameraController.value.isTakingPicture ||
!cameraController.value.isInitialized) {
return;
}
try {
final XFile img = await cameraController.takePicture();
setState(() {
imagesFromCameraRoll.add(img);
});
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}
@override
Widget build(BuildContext context) {
return const Scaffold(
// ...
);
}
}