Reputation: 63
I'm trying to create a camera app in Flutter but I keep bumping into zoom issues. I managed to get the zoom code working via buttons, but when I try to replace those buttons with a GestureDetector, nothing happens.
Below is the camera page. I tried checking if my gestureDetector gets called somewhere by adding a debugLog, but this prints nothing so I think the issue is with calling the detector and not necessarily the code inside the detector
class CameraPreviewPage extends StatefulWidget {
final CameraDescription camera;
CameraPreviewPage({required this.camera});
@override
_CameraPreviewPageState createState() => _CameraPreviewPageState();
}
class _CameraPreviewPageState extends State<CameraPreviewPage> {
late CameraController _cameraController;
late Future<void> _initializeCameraControllerFuture;
double zoom = 1.0;
double _scaleFactor = 1.0;
@override
void initState() {
super.initState();
_cameraController =
CameraController(widget.camera, ResolutionPreset.ultraHigh);
_initializeCameraControllerFuture = _cameraController.initialize();
}
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
FutureBuilder(
future: _initializeCameraControllerFuture,
builder: (context, snapshot) {
//The gestureDetector doesn't work
if (snapshot.connectionState == ConnectionState.done) {
return
GestureDetector(
behavior: HitTestBehavior.translucent,
onScaleStart: (details) {
zoom = _scaleFactor;
},
onScaleUpdate: (details) {
_scaleFactor = zoom * details.scale;
_cameraController.setZoomLevel(_scaleFactor);
debugPrint('Gesture updated');
},
child:CameraPreview(_cameraController));
} else {
return Center(child: CircularProgressIndicator());
}
},
),
SafeArea(
child: Scaffold(
backgroundColor: Colors.transparent,
floatingActionButton:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
FloatingActionButton(
heroTag: "FABZoomIn",
child: Icon(
Icons.zoom_in,
color: Colors.white,
),
onPressed: () {
if (zoom < 8) {
zoom = zoom + 1;
}
_cameraController.setZoomLevel(zoom);
},
backgroundColor: Colors.cyan,
),
SizedBox(
height: 10,
),
FloatingActionButton(
heroTag: "FABZoomOut",
child: Icon(
Icons.zoom_out,
color: Colors.white,
),
onPressed: () {
if (zoom > 1) {
zoom = zoom - 1;
}
_cameraController.setZoomLevel(zoom);
},
backgroundColor: Colors.red,
),
SizedBox(
height: 10,
),
FloatingActionButton(
heroTag: "FABCamera",
child: Icon(Icons.camera, color: Colors.white),
backgroundColor: Colors.green,
onPressed: () {
_takePicture(context);
})
]),
))
],
);
}
@override
void dispose() {
_cameraController.dispose();
super.dispose();
}
}
EDIT: I've also tried using onTap to see if this gives me any more insights in what could be going wrong, but onTap also doesn't get registered.
Upvotes: 0
Views: 3345
Reputation: 6395
This is happening because the first child
inside the children
of a Stack
is rendered first and all the other children
are rendered on top of the first child
.
So, your GestureDetector
will never trigger since the other children are handling the tap and obstructing the GestureDetector
from receiving any hits.
Just move your GestureDetector
to the end of the children
list.
Stack(
children: [
SafeArea(
....
),
GestureDetector(
....
),
],
)
If your definitely need the CameraPreview
at the bottom and the SafeArea
to be rendered on top it, then separate your CameraPreview
into another Container
and have your GestureDetector
as a separate widget at the end of the children
list.
Stack(
children: [
Container(
child: CameraPreview(),
),
SafeArea(
....
),
GestureDetector(
....
),
],
)
Upvotes: 1