首页 > 解决方案 > 用手势检测器拖动

问题描述

我写了一个代码来拖动带有手势检测器的盒子,它可以工作。然后我重构了代码以便于阅读,它也可以工作,但运行速度很慢。有什么问题,我该如何解决?

我尝试将值打印到控制台,那里没有任何问题。

我写了一个代码来拖动带有手势检测器的盒子,它可以工作。然后我重构了代码以便于阅读,它也可以工作,但运行速度很慢。有什么问题,我该如何解决?

我尝试将值打印到控制台,那里没有任何问题。

我写了一个代码来拖动带有手势检测器的盒子,它可以工作。然后我重构了代码以便于阅读,它也可以工作,但运行速度很慢。有什么问题,我该如何解决?

我尝试将值打印到控制台,那里没有任何问题。

// old code that works
   import 'package:flutter/material.dart';

  void main() => runApp(MyApp());


class MyApp extends StatelessWidget {
 // This widget is the root of your application.
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: 'Flutter Demo',
     home: MyHomePage(),
   );
 }
}

class MyHomePage extends StatelessWidget {
 const MyHomePage({
   Key key,
 }) : super(key: key);

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     //so i  can pass the widget size downward
     body: Window(
       size: MediaQuery.of(context).size,
     ),
   );
 }
}

class Window extends StatefulWidget {
 final Size size;

 const Window({Key key,@required this.size}) : super(key: key);

 @override
 _WindowState createState() => _WindowState();
}

class _WindowState extends State<Window> {
 //for reference later
 final boxSize = Size.square(100);
 Offset firstBoxPosition = Offset.zero;
 Offset secondBoxPosition = Offset.zero;
 Offset thirdBoxPosition = Offset.zero;

 @override
 void initState() {
   super.initState();
   //so it starts at the center of the window
   firstBoxPosition = widget.size / 2 - boxSize / 2 as Offset;
   secondBoxPosition = widget.size / 4 - boxSize / 4 as Offset;
   thirdBoxPosition = widget.size / 1.25 - boxSize / 1 as Offset;
 }
 @override
 Widget build(BuildContext context) {
   return Stack(
     children: [
       Positioned(
         top: firstBoxPosition.dy,
         left: firstBoxPosition.dx,
         child: GestureDetector(
           onPanUpdate: (DragUpdateDetails details){
             setState(() {
               //add the previous state of the position to the current state of the drag
               final offset = details.delta + firstBoxPosition;
               //so it doesn't go out of bounds
               //The bound here is zero (the origin) and the size of the window
               final x = offset.dx.clamp(0.0, widget.size.width - boxSize.width);
               final y = offset.dy.clamp(0.0, widget.size.height - boxSize.height);
               firstBoxPosition = Offset(x,y);
             });
           },
           child: SizedBox.fromSize(
             size: boxSize,
             child: Material(color: Colors.green,),
           ),
         ),
       ),
       Positioned(
         top: secondBoxPosition.dy,
         left: secondBoxPosition.dx,
         child: GestureDetector(
           onPanUpdate: (DragUpdateDetails details){
             setState(() {
               //add the previous state of the position to the current state of the drag
               final offset = details.delta + secondBoxPosition;
               //so it doesn't go out of bounds
               //The bound here is zero (the origin) and the size of the window
               final x = offset.dx.clamp(0.0, widget.size.width - boxSize.width);
               final y = offset.dy.clamp(0.0, widget.size.height - boxSize.height);
               secondBoxPosition = Offset(x,y);
             });
           },
           child: SizedBox.fromSize(
             size: boxSize,
             child: Material(color: Colors.blue,),
           ),
         ),
       ),
       Positioned(
         top: thirdBoxPosition.dy,
         left: thirdBoxPosition.dx,
         child: GestureDetector(
           onPanUpdate: (DragUpdateDetails details){
             setState(() {
               //add the previous state of the position to the current state of the drag
               final offset = details.delta + thirdBoxPosition;
               //so it doesn't go out of bounds
               //The bound here is zero (the origin) and the size of the window
               final x = offset.dx.clamp(0.0, widget.size.width - boxSize.width);
               final y = offset.dy.clamp(0.0, widget.size.height - boxSize.height);
               thirdBoxPosition = Offset(x,y);
             });
           },
           child: SizedBox.fromSize(
             size: boxSize,
             child: Material(color: Colors.red,),
           ),
         ),
       ),
     ],
   );
 }
}

//refactored code that's moving slowly

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //so i  can pass the widget size downward
      body: Window(
        size: MediaQuery.of(context).size,
      ),
    );
  }
}

class Window extends StatefulWidget {
  const Window({Key key, @required this.size}) : super(key: key);

  final Size size;

  @override
  _WindowState createState() => _WindowState();
}

class _WindowState extends State<Window> {
  //for reference later
  final boxSize = Size.square(100);

  Offset firstBoxPosition = Offset.zero;
  Offset secondBoxPosition = Offset.zero;
  Offset thirdBoxPosition = Offset.zero;

  Rect get windowBounds => Offset.zero & widget.size;

  @override
  void initState() {
    super.initState();

    // This is not necessary but good for visualization
    final boxCenter = boxSize / 2;
    firstBoxPosition = widget.size / 2 - boxCenter as Offset;
    secondBoxPosition = widget.size / 4 - boxCenter as Offset;
    thirdBoxPosition = widget.size / 1.25 - boxCenter as Offset;
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Box(
          position: firstBoxPosition,
          size: boxSize,
          color: Colors.red,
          bounds: windowBounds,
          onDragged: (position) {
            setState(() {
              firstBoxPosition = position;
            });
          },
        ),
        Box(
          position: secondBoxPosition,
          size: boxSize,
          color: Colors.green,
          bounds: windowBounds,
          onDragged: (position) {
            setState(() {
              secondBoxPosition = position;
            });
          },
        ),
        Box(
          position: thirdBoxPosition,
          size: boxSize,
          color: Colors.blue,
          bounds: windowBounds,
          onDragged: (position) {
            setState(() {
              thirdBoxPosition = position;
            });
          },
        ),
      ],
    );
  }
}

class Box extends Positioned {
  Box({
    Key key,
    @required Rect bounds,
    @required Size size,
    @required Offset position,
    @required Color color,
    @required ValueChanged<Offset> onDragged,
  }) : super(
          key: key,
          top: position.dy,
          left: position.dx,
          width: size.width,
          height: size.height,
          child: GestureDetector(
            onPanUpdate: (DragUpdateDetails details) {
              //add the previous state of the position to the current state of the drag
              final offset = details.delta + position;
              //so it doesn't go out of bounds
              final x = offset.dx.clamp(bounds.left, bounds.right - size.width);
              final y = offset.dy.clamp(bounds.top, bounds.bottom - size.height);
              onDragged.call(Offset(x, y));
            },
            child: Material(color: color),
          ),
        );
}

标签: fluttergesture

解决方案


推荐阅读