Why is the container resizing from the top and bottom at the side time, as well as left and right at the same time?

Viewed 81

I am trying to build a resizable container that can take a child which will then be resizable from either side at a time. But, dragging from one side also drag the opposite side. That is, when dragging the right, the left side is also dragged. same with the top, the top side drags the bottom, vice versa. Please help out. Apologies for the not-so readable code.

         
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Material App Bar'),
        ),
        body: Center(
          child: ResizeableContainer(
            currentHeight: 200,
            currentWidth: 200,
            child: Container(
              color: Colors.yellow,
            ),
          ),
        ),
      ),
    );
  }
}

enum ReferenceSide {
  top,
  bottom,
  left,
  right,
}

double referenceThickness = 4.0;

class ResizeableContainer extends StatefulWidget {
  ResizeableContainer({
    Key? key,
    required this.currentHeight,
    required this.currentWidth,
    required this.child,
  }) : super(key: key);
  double currentWidth;
  double currentHeight;
  Widget child;
  @override
  _ResizeableContainerState createState() => _ResizeableContainerState();
}

class _ResizeableContainerState extends State<ResizeableContainer> {
  @override
  Widget build(BuildContext context) {
    void onHorizontalDragLeft(DragUpdateDetails details) {
      setState(() {
        widget.currentWidth -= details.delta.dx;
      });
    }

    void onHorizontalDragRight(DragUpdateDetails details) {
      setState(() {
        //widget.currentWidth += details.delta.dx;
        widget.currentWidth += details.delta.dx;
      });
    }

    void onVerticalDragUp(DragUpdateDetails details) {
      setState(() {
        widget.currentHeight -= details.delta.dy;
        widget.currentHeight > 0 ? widget.currentHeight : 0;
      });
    }

    void onVerticalDragDown(DragUpdateDetails details) {
      setState(() {
        widget.currentHeight += details.delta.dy;
        widget.currentHeight > 0 ? widget.currentHeight : 0;
      });
    }

    return SizedBox(
      width: widget.currentWidth.clamp(4, 800),
      height: widget.currentHeight.clamp(4, 800),
      child: Stack(
        children: [
          widget.child,
          _DragReferences(
            length: widget.currentWidth,
            side: ReferenceSide.top,
            onDragCallBack: onVerticalDragUp,
          ),
          _DragReferences(
            length: widget.currentWidth,
            side: ReferenceSide.bottom,
            onDragCallBack: onVerticalDragDown,
          ),
          _DragReferences(
            length: widget.currentHeight,
            side: ReferenceSide.left,
            onDragCallBack: onHorizontalDragLeft,
          ),
          _DragReferences(
            length: widget.currentHeight,
            side: ReferenceSide.right,
            onDragCallBack: onHorizontalDragRight,
          )
        ],
      ),
    );
  }
}


class _DragReferences extends StatefulWidget {
  _DragReferences(
      {Key? key, required this.length, required this.side, this.onDragCallBack})
      : super(key: key);

  ReferenceSide side;
  double length;
  void Function(DragUpdateDetails)? onDragCallBack;

  @override
  _DragReferencesState createState() => _DragReferencesState();
}

class _DragReferencesState extends State<_DragReferences> {
  @override
  Widget build(BuildContext context) {
    bool isLeftSide = widget.side == ReferenceSide.left;
    bool isRightSide = widget.side == ReferenceSide.right;
    bool isTopSide = widget.side == ReferenceSide.top;
    bool isBottomSide = widget.side == ReferenceSide.bottom;

    return Positioned(
      left: isRightSide ? null : 0,
      right: isLeftSide ? null : 0,
      top: isBottomSide ? null : 0,
      bottom: isTopSide ? null : 0,
      child: GestureDetector(
        onVerticalDragUpdate:
            isTopSide || isBottomSide ? widget.onDragCallBack : null,
        onHorizontalDragUpdate:
            isLeftSide || isRightSide ? widget.onDragCallBack : null,
        child: _getMouseRegion(side: widget.side, length: widget.length),
      ),
    );
  }
}


Widget _getMouseRegion({required ReferenceSide side, required double length}) {
  bool isVertical = side == ReferenceSide.left || side == ReferenceSide.right;
  return

      
      MouseRegion(
    cursor: isVertical
        ? SystemMouseCursors.resizeLeftRight
        : SystemMouseCursors.resizeUpDown,
    opaque: true,
    child: Container(
      height: isVertical ? length : referenceThickness,
      width: isVertical ? referenceThickness : length,
      color: isVertical ? Colors.amber : Colors.red,
    ),
  );
}
        
1 Answers

This is because you Container is in a Center(). Because of this, the Box always will have the same distance from the left and right side and when you make the box smaller,it is also repositioned. If you want the Container to be in the middle of the Screen, you could the following:

Center(
   child: SizedBox(
   height: 300, // Or whatever works for you
   width: 300,
   child: ResizeableContainer(
      currentHeight: 200,
      currentWidth: 200,
      child: Container(
         color: Colors.yellow,
      ),
   )
),
Related