创建可调整大小的视图,当在 FLUTTER 中从角落和侧面捏或拖动时调整大小 [英] Creating Resizable View that resizes when pinch or drag from corners and sides in FLUTTER
问题描述
我目前正在开发具有可拖动和可调整大小的视图等功能的 ScreenView,如上图所示.我现在遇到的问题是我想通过角落的触摸手势来调整视图的大小.因此,我想到了一个点,我将它添加到选择视图中,可以拖动它来调整选定视图的大小.答案已更新!
Resizable-Widget ReactNative 演示:
更新
我制作了一个简单的原型来展示这个想法.
- 绘制尺寸处理程序和容器;
- 使用 GestureDetector 检测拖动;
- 刷新主容器大小和坐标.
import 'package:flutter/material.dart';无效的主要()=>运行应用程序(我的应用程序());MyApp 类扩展 StatelessWidget {@覆盖小部件构建(BuildContext 上下文){返回材料应用程序(标题:'文本溢出演示',主题:主题数据(primarySwatch:颜色.蓝色,),家:脚手架(正文:演示(),),);}}类演示扩展 StatefulWidget {@覆盖_DemoState createState() =>_DemoState();}class _DemoState 扩展了 State<Demo>{@覆盖小部件构建(BuildContext 上下文){返回容器(填充:EdgeInsets.all(60),孩子:ResizebleWidget(孩子:文本('''我刚刚做了简单的原型来展示主要思想.1. 用容器绘制尺寸处理器;2. 使用 GestureDetector 获取新的尺寸变量3.刷新主容器大小.''',),),);}}类 ResizebleWidget 扩展 StatefulWidget {ResizebleWidget({this.child});最后的小部件子;@覆盖_ResizebleWidgetState createState() =>_ResizebleWidgetState();}常量球直径 = 30.0;class _ResizebleWidgetState 扩展状态{双高 = 400;双宽度 = 200;双顶 = 0;双左= 0;无效 onDrag(双 dx,双 dy){var newHeight = 高度 + dy;var newWidth = 宽度 + dx;设置状态((){高度 = 新高度 >0 ?新高度:0;宽度 = 新宽度 >0 ?新宽度:0;});}@覆盖小部件构建(BuildContext 上下文){返回堆栈(孩子们:<小部件>[定位(顶部:顶部,左:左,孩子:容器(高度:高度,宽度:宽度,颜色:Colors.red[100],孩子:widget.child,),),//左上方定位(顶部:顶部 - ballDiameter/2,左:左 - ballDiameter/2,孩子:操纵球(onDrag: (dx, dy) {变种中间 = (dx + dy)/2;var newHeight = 高度 - 2 * 中;var newWidth = 宽度 - 2 * 中;设置状态((){高度 = 新高度 >0 ?新高度:0;宽度 = 新宽度 >0 ?新宽度:0;顶部 = 顶部 + 中间;左=左+中;});},),),//顶部中间定位(顶部:顶部 - ballDiameter/2,左:左 + 宽度/2 - ballDiameter/2,孩子:操纵球(onDrag: (dx, dy) {var newHeight = 高度 - dy;设置状态((){高度 = 新高度 >0 ?新高度:0;顶部 = 顶部 + dy;});},),),//右上定位(顶部:顶部 - ballDiameter/2,左:左 + 宽度 - ballDiameter/2,孩子:操纵球(onDrag: (dx, dy) {var mid = (dx + (dy * -1))/2;var newHeight = 高度 + 2 * 中;var newWidth = 宽度 + 2 * 中;设置状态((){高度 = 新高度 >0 ?新高度:0;宽度 = 新宽度 >0 ?新宽度:0;顶部 = 顶部 - 中间;左=左-中;});},),),//右中定位(顶部:顶部 + 高度/2 - 球直径/2,左:左 + 宽度 - ballDiameter/2,孩子:操纵球(onDrag: (dx, dy) {var newWidth = 宽度 + dx;设置状态((){宽度 = 新宽度 >0 ?新宽度:0;});},),),//右下角定位(顶部:顶部 + 高度 - ballDiameter/2,左:左 + 宽度 - ballDiameter/2,孩子:操纵球(onDrag: (dx, dy) {变种中间 = (dx + dy)/2;var newHeight = 高度 + 2 * 中;var newWidth = 宽度 + 2 * 中;设置状态((){高度 = 新高度 >0 ?新高度:0;宽度 = 新宽度 >0 ?新宽度:0;顶部 = 顶部 - 中间;左=左-中;});},),),//底部中心定位(顶部:顶部 + 高度 - ballDiameter/2,左:左 + 宽度/2 - ballDiameter/2,孩子:操纵球(onDrag: (dx, dy) {var newHeight = 高度 + dy;设置状态((){高度 = 新高度 >0 ?新高度:0;});},),),//左下方定位(顶部:顶部 + 高度 - ballDiameter/2,左:左 - ballDiameter/2,孩子:操纵球(onDrag: (dx, dy) {var mid = ((dx * -1) + dy)/2;var newHeight = 高度 + 2 * 中;var newWidth = 宽度 + 2 * 中;设置状态((){高度 = 新高度 >0 ?新高度:0;宽度 = 新宽度 >0 ?新宽度:0;顶部 = 顶部 - 中间;左=左-中;});},),),//左中心定位(顶部:顶部 + 高度/2 - 球直径/2,左:左 - ballDiameter/2,孩子:操纵球(onDrag: (dx, dy) {var newWidth = 宽度 - dx;设置状态((){宽度 = 新宽度 >0 ?新宽度:0;左=左+dx;});},),),//居中居中定位(顶部:顶部 + 高度/2 - 球直径/2,左:左 + 宽度/2 - ballDiameter/2,孩子:操纵球(onDrag: (dx, dy) {设置状态((){顶部 = 顶部 + dy;左=左+dx;});},),),],);}}类 ManipulatingBall 扩展 StatefulWidget {ManipulatingBall({Key key, this.onDrag});最终函数 onDrag;@覆盖_ManipulatingBallState createState() =>_ManipulatingBallState();}类_ManipulatingBallState 扩展了State{双初始化X;双重初始化;_handleDrag(详情){设置状态((){initX = details.globalPosition.dx;initY = details.globalPosition.dy;});}_handleUpdate(详细信息){var dx = details.globalPosition.dx - initX;var dy = details.globalPosition.dy - initY;initX = details.globalPosition.dx;initY = details.globalPosition.dy;小部件.onDrag(dx, dy);}@覆盖小部件构建(BuildContext 上下文){返回手势检测器(onPanStart: _handleDrag,onPanUpdate:_handleUpdate,孩子:容器(宽度:球直径,高度:球直径,装饰:盒子装饰(颜色:Colors.blue.withOpacity(0.5),形状:BoxShape.circle,),),);}}
I am currently working on a ScreenView with features like draggable and resizable views with corners and sides like in the image above. The problem I have now is that I want to resize the view by touch gestures in the corners. Therefore, I thought of a Point which I add to a view on selection, which can be dragged to resize the selected view. Answer updated!!
Resizable-Widget ReactNative Demo: React Native PLUGIN example
Modified Workable Example:
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,
),
),
);
}
}
Output:
Updated
I've made a simple prototype to show the idea.
- Draw size handlers and a container;
- Use GestureDetector to detect dragging;
- Refresh the main container size and coordinates.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Text Overflow Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: Demo(),
),
);
}
}
class Demo extends StatefulWidget {
@override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(60),
child: ResizebleWidget(
child: Text(
'''I've just did simple prototype to show main idea.
1. Draw size handlers with container;
2. Use GestureDetector to get new variables of sizes
3. Refresh the main container size.''',
),
),
);
}
}
class ResizebleWidget extends StatefulWidget {
ResizebleWidget({this.child});
final Widget child;
@override
_ResizebleWidgetState createState() => _ResizebleWidgetState();
}
const ballDiameter = 30.0;
class _ResizebleWidgetState extends State<ResizebleWidget> {
double height = 400;
double width = 200;
double top = 0;
double left = 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;
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;
});
},
),
),
// top middle
Positioned(
top: top - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newHeight = height - dy;
setState(() {
height = newHeight > 0 ? newHeight : 0;
top = top + dy;
});
},
),
),
// 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(() {
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top - mid;
left = left - mid;
});
},
),
),
// center right
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left + width - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newWidth = width + dx;
setState(() {
width = newWidth > 0 ? newWidth : 0;
});
},
),
),
// 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(() {
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top - mid;
left = left - mid;
});
},
),
),
// bottom center
Positioned(
top: top + height - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newHeight = height + dy;
setState(() {
height = newHeight > 0 ? newHeight : 0;
});
},
),
),
// 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(() {
height = newHeight > 0 ? newHeight : 0;
width = newWidth > 0 ? newWidth : 0;
top = top - mid;
left = left - mid;
});
},
),
),
//left center
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
var newWidth = width - dx;
setState(() {
width = newWidth > 0 ? newWidth : 0;
left = left + dx;
});
},
),
),
// center center
Positioned(
top: top + height / 2 - ballDiameter / 2,
left: left + width / 2 - ballDiameter / 2,
child: ManipulatingBall(
onDrag: (dx, dy) {
setState(() {
top = top + dy;
left = left + dx;
});
},
),
),
],
);
}
}
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,
),
),
);
}
}
这篇关于创建可调整大小的视图,当在 FLUTTER 中从角落和侧面捏或拖动时调整大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!