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,
),
);
}