Created
June 17, 2021 08:03
-
-
Save jazzbpn/9ac1cd5ccea543dc3c16c0c20afdddec to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
class ResizebleWidget extends StatefulWidget { | |
final Widget child; | |
final String widgetId; | |
final Size size; | |
final bool editMode, doubleTapped; | |
final GestureTapCallback onSingleTapWidget, onDoubleTapWidget; | |
ResizebleWidget( | |
{this.child, | |
this.widgetId, | |
this.size, | |
this.editMode, | |
this.doubleTapped, | |
this.onSingleTapWidget, | |
this.onDoubleTapWidget}); | |
@override | |
_ResizebleWidgetState createState() => _ResizebleWidgetState(); | |
} | |
const ballDiameter = 25.0; | |
class _ResizebleWidgetState extends State<ResizebleWidget> { | |
double top = 0; | |
double left = 0; | |
double height = 0; | |
double width = 0; | |
bool editable; | |
double rotateAngle = 0; | |
@override | |
void initState() { | |
height = widget.size.height; | |
width = widget.size.width; | |
super.initState(); | |
} | |
void onDrag(double dx, double dy) { | |
var newHeight = height + dy; | |
var newWidth = width + dx; | |
setState(() { | |
height = newHeight > 0 ? newHeight : 0; | |
width = newWidth > 0 ? newWidth : 0; | |
}); | |
} | |
showBoxDecoration() { | |
return BoxDecoration( | |
border: Border.all( | |
color: editable == true ? Colors.lightBlue : Colors.transparent, | |
width: editable == true ? 1 : 0, | |
), | |
); | |
} | |
@override | |
Widget build(BuildContext context) { | |
editable = widget.editMode; | |
return Transform.rotate( | |
angle: rotateAngle, | |
child: Stack( | |
children: <Widget>[ | |
Positioned( | |
top: top, | |
left: left, | |
child: GestureDetector( | |
onTap: widget.onSingleTapWidget, | |
child: Container( | |
decoration: showBoxDecoration(), | |
height: height, | |
width: width, | |
child: widget.child, | |
), | |
), | |
), | |
// center center | |
editable && widget.doubleTapped == false | |
? Positioned( | |
top: top, // look 20 form transparent draggable widget | |
left: left, | |
child: InkWell( | |
onDoubleTap: () { | |
widget.onDoubleTapWidget(); | |
}, | |
child: ManipulatingBall( | |
height: height, | |
width: width, | |
color: Colors.red.withOpacity(0.6), | |
onDrag: (dx, dy, details) { | |
setState(() { | |
top = top + dy; | |
left = left + dx; | |
}); | |
}, | |
), | |
), | |
) | |
: Container(), | |
// top left | |
editable | |
? Positioned( | |
top: top - ballDiameter / 2, | |
left: left - ballDiameter / 2, | |
child: ManipulatingBall( | |
onDrag: (dx, dy, details) { | |
var mid = (dx + dy) / 2; | |
var newHeight = height - 2 * mid; | |
var newWidth = width - 2 * mid; | |
setState(() { | |
height = newHeight > 0 ? newHeight : 0; | |
width = newWidth > 0 ? newWidth : 0; | |
top = top + mid; | |
left = left + mid; | |
}); | |
}, | |
), | |
) | |
: Container(), | |
// top middle | |
editable | |
? Positioned( | |
top: top - ballDiameter / 2, | |
left: left + width / 2 - ballDiameter / 2, | |
child: ManipulatingBall( | |
onDrag: (dx, dy, details) { | |
var newHeight = height - dy; | |
setState(() { | |
height = newHeight > 0 ? newHeight : 0; | |
top = top + dy; | |
}); | |
}, | |
), | |
) | |
: Container(), | |
// top right | |
editable | |
? Positioned( | |
top: top - ballDiameter / 2, | |
left: left + width - ballDiameter / 2, | |
child: ManipulatingBall( | |
onDrag: (dx, dy, details) { | |
var mid = (dx + (dy * -1)) / 2; | |
var newHeight = height + 2 * mid; | |
var newWidth = width + 2 * mid; | |
setState(() { | |
height = newHeight > 0 ? newHeight : 0; | |
width = newWidth > 0 ? newWidth : 0; | |
top = top - mid; | |
left = left - mid; | |
}); | |
}, | |
), | |
) | |
: Container(), | |
// center right | |
editable | |
? Positioned( | |
top: top + height / 2 - ballDiameter / 2, | |
left: left + width - ballDiameter / 2, | |
child: ManipulatingBall( | |
onDrag: (dx, dy, details) { | |
var newWidth = width + dx; | |
setState(() { | |
width = newWidth > 0 ? newWidth : 0; | |
}); | |
}, | |
), | |
) | |
: Container(), | |
// bottom right | |
editable | |
? Positioned( | |
top: top + height - ballDiameter / 2, | |
left: left + width - ballDiameter / 2, | |
child: ManipulatingBall( | |
onDrag: (dx, dy, details) { | |
var mid = (dx + dy) / 2; | |
var newHeight = height + 2 * mid; | |
var newWidth = width + 2 * mid; | |
setState(() { | |
height = newHeight > 0 ? newHeight : 0; | |
width = newWidth > 0 ? newWidth : 0; | |
top = top - mid; | |
left = left - mid; | |
}); | |
}, | |
), | |
) | |
: Container(), | |
// bottom center | |
editable | |
? Positioned( | |
top: top + height - ballDiameter / 2, | |
left: left + width / 2 - ballDiameter / 2, | |
child: ManipulatingBall( | |
onDrag: (dx, dy, details) { | |
var newHeight = height + dy; | |
setState(() { | |
height = newHeight > 0 ? newHeight : 0; | |
}); | |
}, | |
), | |
) | |
: Container(), | |
// bottom left | |
editable | |
? Positioned( | |
top: top + height - ballDiameter / 2, | |
left: left - ballDiameter / 2, | |
child: ManipulatingBall( | |
onDrag: (dx, dy, details) { | |
var mid = ((dx * -1) + dy) / 2; | |
var newHeight = height + 2 * mid; | |
var newWidth = width + 2 * mid; | |
setState(() { | |
height = newHeight > 0 ? newHeight : 0; | |
width = newWidth > 0 ? newWidth : 0; | |
top = top - mid; | |
left = left - mid; | |
}); | |
}, | |
), | |
) | |
: Container(), | |
//left center | |
editable | |
? Positioned( | |
top: top + height / 2 - ballDiameter / 2, | |
left: left - ballDiameter / 2, | |
child: ManipulatingBall( | |
onDrag: (dx, dy, details) { | |
var newWidth = width - dx; | |
setState(() { | |
width = newWidth > 0 ? newWidth : 0; | |
left = left + dx; | |
}); | |
}, | |
), | |
) | |
: Container(), | |
// bottom center center to Rotate-resizable-widget | |
editable | |
? Positioned( | |
top: top + height + ballDiameter, | |
left: left + width / 2 - ballDiameter / 2, | |
child: Stack( | |
children: [ | |
Icon( | |
Icons.refresh, | |
color: Colors.black, | |
size: 40, | |
), | |
ManipulatingBall( | |
onDrag: (dx, dy, details) { | |
final touchPositionFromCenter = details.localPosition; | |
setState( | |
() { | |
rotateAngle = touchPositionFromCenter.direction; | |
print('Rotate--> ' + rotateAngle.toString()); | |
}, | |
); | |
}, | |
), | |
], | |
)) | |
: Container(), | |
], | |
), | |
); | |
} | |
} | |
class ManipulatingBall extends StatefulWidget { | |
ManipulatingBall({Key key, this.onDrag, this.height, this.color, this.width}); | |
final Function onDrag; | |
final double height, width; | |
final Color color; | |
@override | |
_ManipulatingBallState createState() => _ManipulatingBallState(); | |
} | |
class _ManipulatingBallState extends State<ManipulatingBall> { | |
double initX; | |
double initY; | |
_handleDrag(details) { | |
setState(() { | |
initX = details.globalPosition.dx; | |
initY = details.globalPosition.dy; | |
}); | |
} | |
_handleUpdate(details) { | |
var dx = details.globalPosition.dx - initX; | |
var dy = details.globalPosition.dy - initY; | |
initX = details.globalPosition.dx; | |
initY = details.globalPosition.dy; | |
widget.onDrag(dx, dy, details); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return GestureDetector( | |
behavior: HitTestBehavior.translucent, | |
onPanStart: _handleDrag, | |
onPanUpdate: _handleUpdate, | |
child: Container( | |
width: widget.width == null ? ballDiameter : widget.width, | |
height: widget.height == null ? ballDiameter : widget.height, | |
decoration: BoxDecoration( | |
color: widget.color == null | |
? Colors.blue.withOpacity(0.5) | |
: widget.color, | |
shape: widget.width == null ? BoxShape.circle : BoxShape.rectangle, | |
), | |
), | |
); | |
} | |
} |
Author
jazzbpn
commented
Jun 17, 2021
I want the end result like this https://streamable.com/faq9ia.
After resizing widget
- rotation should work from center and
- the resize pointer should work fine.
Please note after using FooResizer() I keep getting same result like https://streamable.com/oogp5f
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment