私は現在、上の画像のように、コーナーとサイドを備えたドラッグ可能およびサイズ変更可能なビューなどの機能を持つScreenViewに取り組んでいます。私が今持っている問題は、隅のタッチジェスチャーでビューのサイズを変更したいということです。そのため、選択時にビューに追加するポイントを考えました。ポイントをドラッグすると、選択したビューのサイズを変更できます。回答を更新しました!!
Resizable-Widget ReactNative Demo:React Native PLUGINの例
変更された実行可能な例:
import 'package:flutter/material.Dart';
class ResizeWidget extends StatefulWidget {
@override
_ResizeWidgetState createState() => _ResizeWidgetState();
}
class _ResizeWidgetState extends State<ResizeWidget> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
body: Container(
// padding: EdgeInsets.only(top: 50),
child: ResizebleWidget(
child: Container(
padding: EdgeInsets.all(10),
child: Text(
'Waao!! you can really dance.',
style: TextStyle(
color: Colors.white,
fontStyle: FontStyle.italic,
fontSize: 18),
),
),
),
),
),
);
}
}
class ResizebleWidget extends StatefulWidget {
ResizebleWidget({this.child});
final Widget child;
@override
_ResizebleWidgetState createState() => _ResizebleWidgetState();
}
const ballDiameter = 10.0;
class _ResizebleWidgetState extends State<ResizebleWidget> {
double height = 100;
double width = 200;
bool isCorner = false;
double top = 0;
double left = 0;
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
top: top,
left: left,
child: Container(
height: height,
width: width,
decoration: BoxDecoration(
color: Colors.blueGrey,
border: Border.all(
width: 2,
color: Colors.white70,
),
borderRadius: BorderRadius.circular(0.0),
),
// need tp check if draggable is done from corner or sides
child: isCorner
? FittedBox(
child: widget.child,
)
: Center(
child: widget.child,
),
),
),
// top left
Positioned(
top: top - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = (dx + dy) / 2;
var newHeight = height - 2 * mid;
var newWidth = width - 2 * mid;
setState(() {
isCorner = true;
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top + mid;
left = left + mid;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
// top middle
Positioned(
top: top - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newHeight = height - dy;
setState(() {
isCorner = false;
height = newHeight > 0 ? newHeight : 0;
top = top + dy;
});
},
handlerWidget: HandlerWidget.HORIZONTAL,
),
),
// top right
Positioned(
top: top - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = (dx + (dy * -1)) / 2;
var newHeight = height + 2 * mid;
var newWidth = width + 2 * mid;
setState(() {
isCorner = true;
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top - mid;
left = left - mid;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
// center right
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newWidth = width + dx;
setState(() {
isCorner = false;
width = newWidth > 0 ? newWidth : 0;
});
},
handlerWidget: HandlerWidget.HORIZONTAL,
),
),
// bottom right
Positioned(
top: top + height - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = (dx + dy) / 2;
var newHeight = height + 2 * mid;
var newWidth = width + 2 * mid;
setState(() {
isCorner = true;
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top - mid;
left = left - mid;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
// bottom center
Positioned(
top: top + height - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newHeight = height + dy;
setState(() {
isCorner = false;
height = newHeight > 0 ? newHeight : 0;
});
},
handlerWidget: HandlerWidget.HORIZONTAL,
),
),
// bottom left
Positioned(
top: top + height - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = ((dx * -1) + dy) / 2;
var newHeight = height + 2 * mid;
var newWidth = width + 2 * mid;
setState(() {
isCorner = true;
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top - mid;
left = left - mid;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
//left center
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newWidth = width - dx;
setState(() {
isCorner = false;
width = newWidth > 0 ? newWidth : 0;
left = left + dx;
});
},
handlerWidget: HandlerWidget.HORIZONTAL,
),
),
// center center
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
setState(() {
isCorner = false;
top = top + dy;
left = left + dx;
});
},
handlerWidget: HandlerWidget.VERTICAL,
),
),
],
);
}
}
class ManipulatingBall extends StatefulWidget {
ManipulatingBall({Key key, this.onDrag, this.handlerWidget});
final Function onDrag;
final HandlerWidget handlerWidget;
@override
_ManipulatingBallState createState() => _ManipulatingBallState();
}
enum HandlerWidget { HORIZONTAL, VERTICAL }
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);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanStart: _handleDrag,
onPanUpdate: _handleUpdate,
child: Container(
width: ballDiameter,
height: ballDiameter,
decoration: BoxDecoration(
color: Colors.white,
shape: this.widget.handlerWidget == HandlerWidget.VERTICAL
? BoxShape.circle
: BoxShape.rectangle,
),
),
);
}
}
出力:
上記のコードのディスクリートバージョン(つまり、50ユニットごとにスナップ)を実行して、誰かに役立つ場合:
import 'package:flutter/material.Dart';
class DiscreteResizableComponent extends StatefulWidget {
const DiscreteResizableComponent({Key key, this.child}):super(key:key);
final Widget child;
@override
_ResizebleWidgetState createState() => _ResizebleWidgetState();
}
const ballDiameter = 30.0;
const discreteStepSize = 50;
class _ResizebleWidgetState extends State<DiscreteResizableComponent> {
double height = 400;
double width = 200;
double top = 0;
double left = 0;
double cumulativeDy=0;
double cumulativeDx=0;
double cumulativeMid = 0;
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;
});
}
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
top: top,
left: left,
child: Container(
height: height,
width: width,
color: Colors.red[100],
child: widget.child,
),
),
// top left
Positioned(
top: top - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = (dx + dy) / 2;
cumulativeMid -= 2*mid;
if(cumulativeMid>=discreteStepSize)
{
setState(() {
var newHeight = height+discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
var newWidth = width +discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeMid=0;
});
}
else if(cumulativeMid<=-discreteStepSize)
{
setState(() {
var newHeight = height - discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
var newWidth = width - discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeMid=0;
});
}
},
),
),
// top middle
Positioned(
top: top - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
cumulativeDy -= dy;
if(cumulativeDy>=discreteStepSize)
{
setState(() {
var newHeight = height+discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
cumulativeDy=0;
});
}
else if(cumulativeDy<=-discreteStepSize)
{
setState(() {
var newHeight = height - discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
cumulativeDy=0;
});
}
},
),
),
// top right
Positioned(
top: top - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = (dx + (dy * -1)) / 2;
cumulativeMid += 2*mid;
if(cumulativeMid>=discreteStepSize)
{
setState(() {
var newHeight = height+discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
var newWidth = width +discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeMid=0;
});
}
else if(cumulativeMid<=-discreteStepSize)
{
setState(() {
var newHeight = height - discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
var newWidth = width - discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeMid=0;
});
}
},
),
),
// center right
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
cumulativeDx += dx;
if(cumulativeDx>=discreteStepSize)
{
setState(() {
var newWidth = width+discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeDx=0;
});
}
else if(cumulativeDx<=-discreteStepSize)
{
setState(() {
var newWidth = width-discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeDx=0;
});
}
},
),
),
// bottom right
Positioned(
top: top + height - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = (dx + dy) / 2;
cumulativeMid += 2*mid;
if(cumulativeMid>=discreteStepSize)
{
setState(() {
var newHeight = height+discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
var newWidth = width +discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeMid=0;
});
}
else if(cumulativeMid<=-discreteStepSize)
{
setState(() {
var newHeight = height - discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
var newWidth = width - discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeMid=0;
});
}
},
),
),
// bottom center
Positioned(
top: top + height - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
cumulativeDy += dy;
if(cumulativeDy>=discreteStepSize)
{
setState(() {
var newHeight = height+discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
cumulativeDy=0;
});
}
else if(cumulativeDy<=-discreteStepSize)
{
setState(() {
var newHeight = height-discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
cumulativeDy=0;
});
}
},
),
),
// bottom left
Positioned(
top: top + height - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var mid = ((dx * -1) + dy) / 2;
cumulativeMid += 2*mid;
if(cumulativeMid>=discreteStepSize)
{
setState(() {
var newHeight = height+discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
var newWidth = width +discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeMid=0;
});
}
else if(cumulativeMid<=-discreteStepSize)
{
setState(() {
var newHeight = height - discreteStepSize;
height = newHeight > 0 ? newHeight : 0;
var newWidth = width - discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeMid=0;
});
}
},
),
),
//left center
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
cumulativeDx -= dx;
if(cumulativeDx>=discreteStepSize)
{
setState(() {
var newWidth = width+discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeDx=0;
});
}
else if(cumulativeDx<=-discreteStepSize)
{
setState(() {
var newWidth = width-discreteStepSize;
width = newWidth > 0 ? newWidth : 0;
cumulativeDx=0;
});
}
},
),
),
],
);
}
}
class ManipulatingBall extends StatefulWidget {
ManipulatingBall({Key key, this.onDrag});
final Function onDrag;
@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);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanStart: _handleDrag,
onPanUpdate: _handleUpdate,
child: Container(
width: ballDiameter,
height: ballDiameter,
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.5),
shape: BoxShape.circle,
),
),
);
}
}