简体   繁体   English

如何在Flutter中实现可滚动画布?

[英]How to achieve scrollable canvas in Flutter?

I'm a experienced iOS developer, but completely new to the Flutter. 我是一位经验丰富的iOS开发人员,但对于Flutter来说却是全新的。 Right now I'm facing a problem with ScrollView in Flutter. 现在我在Flutter中遇到了ScrollView的问题。

What I want to achieve is building a large scrollable canvas. 我想要实现的是构建一个大型可滚动画布。 I did it on iOS before, you can see the screenshot here. 我之前在iOS上做过,你可以在这里看到截图。

iOS UI

The canvas is a big UIScrollView, and each subview on the canvas is draggable, so I can place them at will. 画布是一个很大的UIScrollView,画布上的每个子视图都是可拖动的,所以我可以随意放置它们。 Even if the text is very long, I can scroll the canvas to see the full content. 即使文本很长,我也可以滚动画布来查看完整内容。 Now I need to do the same thing using Flutter. 现在我需要使用Flutter做同样的事情。

Currently, I can only drag the text widgets in Flutter. 目前,我只能在Flutter中拖动文本小部件。 But the parent widget is not scrollable. 但是父窗口小部件不可滚动。 I know I need to use a scrollable widget in Flutter to achieve the same result, but I just can't make it work. 我知道我需要在Flutter中使用可滚动的小部件来实现相同的结果,但我无法使其工作。 Here's the code I currently have. 这是我目前的代码。

void main() {
  //debugPaintLayerBordersEnabled = true;
  //debugPaintSizeEnabled = true;
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        title: 'Flutter Demo',
        theme: new ThemeData(
        primarySwatch: Colors.indigo,
      ),
      home: new MyHomePage(title: 'Flutter Demo Drag Box'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
      title: new Text(title),
    ),
    body: DragBox(Offset(0.0, 0.0)));
  }
}

class DragBox extends StatefulWidget {
  final Offset position; // widget's position
  DragBox(this.position);

  @override
  _DragBoxState createState() => new _DragBoxState();
}

class _DragBoxState extends State<DragBox> {
  Offset _previousOffset;
  Offset _offset;
  Offset _position;

  @override
  void initState() {
    _offset = Offset.zero;
    _previousOffset = Offset.zero;
    _position = widget.position;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      constraints: BoxConstraints.expand(),
      color: Colors.white24,
      child: Stack(
        children: <Widget>[
        buildDraggableBox(1, Colors.red, _offset)
      ],
    )
  );
}

Widget buildDraggableBox(int boxNumber, Color color, Offset offset) {
  print('buildDraggableBox $boxNumber !');
  return new Stack(
    children: <Widget>[
      new Positioned(
        left: _position.dx,
        top: _position.dy,
        child: Draggable(
          child: _buildBox(color, offset),
          feedback: _buildBox(color, offset),
          //childWhenDragging: _buildBox(color, offset, onlyBorder: true),
          onDragStarted: () {
            print('Drag started !');
            setState(() {
              _previousOffset = _offset;
            });
            print('Start position: $_position}');
          },
          onDragCompleted: () {
            print('Drag complete !');
          },
          onDraggableCanceled: (Velocity velocity, Offset offset) {
            // update position here
            setState(() {
              Offset _offset = Offset(offset.dx, offset.dy - 80);
              _position = _offset;
              print('Drag canceled position: $_position');
            });
          },
        ),
      )
    ],
  );
}

Widget _buildBox(Color color, Offset offset, {bool onlyBorder: false}) {
  return new Container(
    child: new Text('Flutter widget',
      textAlign: TextAlign.center,
      style: new TextStyle(fontWeight: FontWeight.bold, fontSize: 25.0)),
    );
  }
}

Any suggestions or code samples would be really helpful to me. 任何建议或代码示例对我都非常有帮助。

PS: Please forget about the rulers on the screenshot, it's not the most important thing to me right now. PS:请忘记截图上的统治者,这对我来说不是最重要的事情。 I just need a big scrollable canvas now. 我现在只需要一个可滚动的大画布。

The below Code may help to resolve your problem it scroll the custom canvas in horizontal direction as you have shown in example image. 以下代码可能有助于解决您在示例图像中显示的水平方向滚动自定义画布的问题。

     import 'package:flutter/material.dart';

      class MyScroll extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return new MaterialApp(
            title: 'Flutter Demo',
            theme: new ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: new MyHomePage(title: 'Canvas Scroller'),
          );
        }
      }
      class MyHomePage extends StatefulWidget {
        MyHomePage({Key key, this.title}) : super(key: key);
        final String title;

        @override
        _MyHomePageState createState() => new _MyHomePageState();
      }
      class _MyHomePageState extends State<MyHomePage> {
        @override
        Widget build(BuildContext context) {
          final width = MediaQuery.of(context).size.width;
          final height = MediaQuery.of(context).size.height;
          return new Scaffold(
            appBar: new AppBar(
              title: new Text(widget.title),
            ),
            body: new Center(
              child: new SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: new CustomPaint(
                  painter: new MyCanvasView(),
                  size: new Size(width*2, height/2),
                ),
              ),
            ),
          );
        }
      }

      class MyCanvasView extends CustomPainter{
        @override
        void paint(Canvas canvas, Size size) {
          var paint = new Paint();
          paint..shader = new LinearGradient(colors: [Colors.yellow[700], Colors.redAccent],
             begin: Alignment.centerRight, end: Alignment.centerLeft).createShader(new Offset(0.0, 0.0)&size);
          canvas.drawRect(new Offset(0.0, 0.0)&size, paint);
          var path = new Path();
          path.moveTo(0.0, size.height);
          path.lineTo(1*size.width/4, 0*size.height/4);
          path.lineTo(2*size.width/4, 2*size.height/4);
          path.lineTo(3*size.width/4, 0*size.height/4);
          path.lineTo(4*size.width/4, 4*size.height/4);
          canvas.drawPath(path, new Paint()..color = Colors.yellow ..strokeWidth = 4.0 .. style = PaintingStyle.stroke);
        }

        @override
        bool shouldRepaint(CustomPainter oldDelegate) {
          return false;
        }

      }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM