Instead of using the specified height, the Container
that is the GestureDetector
child and AspectRatio
parent is filling all the available space (the stack that this widget is used in which is also the boundaryHeight). The purpose of this widget is to be able to drag it around within the parent or specified boundary width/height. Basically a custom Draggable
with more flexibility and no need for DragTarget
.
EDIT: Thanks to comments and answers, I know it is related to missing constraints, but how can those be added?
Here is the widget:
class OurDraggable extends ConsumerStatefulWidget {
final double? boundaryHeight;
final double? boundaryWidth;
final double? height;
final double? width;
final double? aspectRatio;
final Widget child;
const OurDraggable({
Key? key,
this.boundaryHeight,
this.boundaryWidth,
this.height,
this.width,
this.aspectRatio,
required this.child,
}) : super(key: key);
@override
DraggablePreviewState createState() => DraggablePreviewState();
}
class DraggablePreviewState extends ConsumerState<OurDraggable> {
late Offset _offset = const Offset(0, 0);
late Offset _maxOffset;
void _updateMaxOffset(double boundaryWidth, double boundaryHeight) {
_maxOffset = Offset(
widget.boundaryWidth ??
boundaryWidth - (widget.height! * widget.aspectRatio!),
widget.boundaryHeight ?? boundaryHeight - widget.height!,
);
}
void _updateOffset(DragUpdateDetails dragUpdateDetails) {
double newXOffset = _offset.dx + dragUpdateDetails.delta.dx;
double newYOffset = _offset.dy + dragUpdateDetails.delta.dy;
if (newXOffset < 0) {
newXOffset = 0;
} else if (newXOffset > _maxOffset.dx) {
newXOffset = _maxOffset.dx;
}
if (newYOffset < 0) {
newYOffset = 0;
} else if (newYOffset > _maxOffset.dy) {
newYOffset = _maxOffset.dy;
}
setState(() {
_offset = Offset(
newXOffset,
newYOffset,
);
});
}
@override
Widget build(BuildContext context) {
assert((widget.height != null ||
widget.width != null && widget.aspectRatio != null) ||
widget.height != null && widget.width != null);
assert(widget.height == null ||
widget.width == null && widget.aspectRatio != null);
return LayoutBuilder(
builder: (context, constraints) {
_updateMaxOffset(constraints.maxWidth, constraints.maxHeight);
return SizedBox(
height: widget.boundaryHeight ?? constraints.maxHeight,
width: widget.boundaryWidth ?? constraints.maxWidth,
child: GestureDetector(
onPanUpdate: _updateOffset,
child: Container( //This is the container that has the problem sizing
clipBehavior: Clip.antiAlias,
transform: Matrix4.identity()..translate(_offset.dx, _offset.dy),
height: 250,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
),
child: AspectRatio(
aspectRatio: widget.aspectRatio!,
child: widget.child,
),
),
),
);
},
);
}
}