创建可调整大小的视图,当在 FLUTTER 中从角落和侧面捏或拖动时调整大小 [英] Creating Resizable View that resizes when pinch or drag from corners and sides in FLUTTER

查看:27
本文介绍了创建可调整大小的视图,当在 FLUTTER 中从角落和侧面捏或拖动时调整大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发具有可拖动和可调整大小的视图等功能的 ScreenView,如上图所示.我现在遇到的问题是我想通过角落的触摸手势来调整视图的大小.因此,我想到了一个点,我将它添加到选择视图中,可以拖动它来调整选定视图的大小.答案已更新!

Resizable-Widget ReactNative 演示:

解决方案

更新

我制作了一个简单的原型来展示这个想法.

  1. 绘制尺寸处理程序和容器;
  2. 使用 GestureDetector 检测拖动;
  3. 刷新主容器大小和坐标.

 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.

  1. Draw size handlers and a container;
  2. Use GestureDetector to detect dragging;
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆