1

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,
              ),
            ),
          ),
        );
      },
    );
  }
}
Jacob Miller
  • 562
  • 4
  • 16

1 Answers1

0

you can read about container at line 113: https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/widgets/container.dart

ThanhNguyen
  • 162
  • 3