创建可调整大小的视图,当在FLUTTER中从角落和侧面挤压或拖动时会调整大小

问题描述 投票:1回答:1

enter image description here

我目前正在使用一个ScreenView,它具有诸如可拖动和可调整大小的视图等功能,如上图所示,带有角和边。现在的问题是我想通过角落的触摸手势来调整视图的大小。因此,我想到了一个点,可以将其添加到选择视图中,可以将其拖动以调整所选视图的大小。

即使经过长时间的研究,我也无法提出如何叠加另一个具有自己的DragListener的视图的解决方案。有人有这个问题的经验吗?预先谢谢你。

Resizable-Widget演示

ReactNative Demo: React Native PLUGIN example

JS DEMO(转到缩放部分): JS Example, GOTO RESIZING section

使用@Kherel示例的修改代码。

  import 'package:flutter/material.dart';

  class DrawResizableWidget extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Text Overflow Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          body: DemoWidget(),
          backgroundColor: Colors.black,
        ),
      );
    }
  }

  class DemoWidget extends StatefulWidget {
    @override
    _DemoWidgetState createState() => _DemoWidgetState();
  }

  class _DemoWidgetState extends State<DemoWidget> {
    @override
    Widget build(BuildContext context) {
      return Container(
        padding: EdgeInsets.all(20),
        margin: EdgeInsets.only(top: 30),
        child: ResizebleWidget(
          child:
              // Image.asset('assets/blur.jpg'),
              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 = 20.0;

  class _ResizebleWidgetState extends State<ResizebleWidget> {
    double height = 400;
    double width = 200;

    Function onDragStart(String name) => (dx, 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 Container(
        height: height + ballDiameter / 2,
        width: width + ballDiameter / 2,
        alignment: Alignment.center,
        child: Stack(
          children: <Widget>[
            Positioned(
              top: 0,
              left: 0,
              child: Container(
                height: height,
                width: width,
                color: Colors.white70,
                child: widget.child,
              ),
            ),
            Positioned(
              right: 0,
              bottom: 0,
              child: ManipulatingBall(
                onDragStart: onDragStart('start'),
              ),
            ),
            Positioned(
              right: width / 2,
              bottom: 0,
              child: ManipulatingBall(
                onDragStart: onDragStart('start'),
              ),
            ),
            Positioned(
              right: 0,
              bottom: height / 2,
              child: ManipulatingBall(
                onDragStart: onDragStart('start'),
              ),
            ),
            Positioned(
              top: 0,
              left: width,
              child: ManipulatingBall(
                onDragStart: onDragStart('start'),
              ),
            ),
            Positioned(
              top: 0,
              left: 0,
              child: ManipulatingBall(
                onDragStart: onDragStart('start'),
              ),
            ),
            Positioned(
              left: 0,
              top: height / 2,
              child: ManipulatingBall(
                onDragStart: onDragStart('start'),
              ),
            ),
            Positioned(
              left: 0,
              top: height - 10,
              child: ManipulatingBall(
                onDragStart: onDragStart('start'),
              ),
            ),
          ],
        ),
      );
    }
  }

  class ManipulatingBall extends StatefulWidget {
    ManipulatingBall({Key key, this.onDragStart});

    final Function onDragStart;

    @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.onDragStart(dx, dy);
    }

    @override
    Widget build(BuildContext context) {
      return GestureDetector(
        onPanStart: _handleDrag,
        onPanUpdate: _handleUpdate,
        child: Container(
          width: ballDiameter,
          height: ballDiameter,
          decoration: BoxDecoration(
            color: Colors.red.withOpacity(0.5),
            shape: BoxShape.circle,
          ),
        ),
      );
    }
  }

当前代码输出:

enter image description here

当前问题:

  1. 从像左上角的角落拖动不起作用。

  2. ManipulatingBall不是确切的角。

  3. 无法像所有侧面的中间部分一样使矩形处理程序。

flutter resize flutter-layout image-resizing window-resize
1个回答
0
投票

更新

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

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

enter image description here

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 newHeight = height - dy;
              var newWidth = width - dx;

              setState(() {
                height = newHeight > 0 ? newHeight : 0;
                width = newWidth > 0 ? newWidth : 0;
                top = top + dy;
                left = left + dx;
              });
            },
          ),
        ),
        // 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 newHeight = height - dy;
              var newWidth = width + dx;

              setState(() {
                height = newHeight > 0 ? newHeight : 0;
                width = newWidth > 0 ? newWidth : 0;
                top = top + dy;
              });
            },
          ),
        ),
        // 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 newHeight = height + dy;
              var newWidth = width + dx;

              setState(() {
                height = newHeight > 0 ? newHeight : 0;
                width = newWidth > 0 ? newWidth : 0;
              });
            },
          ),
        ),
        // 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 newHeight = height + dy;
              var newWidth = width - dx;

              setState(() {
                height = newHeight > 0 ? newHeight : 0;
                width = newWidth > 0 ? newWidth : 0;
                left = left + dx;
              });
            },
          ),
        ),
        //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,
        ),
      ),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.