dart Flutter将支持从右向左拖动添加到示例代码

ibps3vxo  于 12个月前  发布在  Flutter
关注(0)|答案(3)|浏览(119)

在这里提供的完整代码中,left to right中的drag-and-drop工作得很好,允许我显示底层小部件。现在,我想介绍的更改是如何将right to left中的drag-and-drop添加到它,以便我可以将顶部小部件移动到左侧。
我的意思是,我怎样才能将从左到右的反向拖放操作添加到它呢?

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        brightness: Brightness.dark,
      ),
      home: const MyHome(),
    );
  }
}

class MyHome extends StatefulWidget {
  const MyHome();

  @override
  State<StatefulWidget> createState() => _MyHome();
}

class _MyHome extends State<MyHome>  with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  final double maxSlide = 225.0;
  final double minDragStartEdge = 150.0;
  final double maxDragStartEdge = 250.0;
  bool _canBeDragged = true;

  @override
  void initState() {
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 250),
    );
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onHorizontalDragStart: _onDragStart,
        onHorizontalDragUpdate: _onDragUpdate,
        onHorizontalDragEnd: _onDragEnd,
        child: AnimatedBuilder(
          animation: _animationController,
          builder: (BuildContext context, _) {
            final slide = maxSlide * _animationController.value;
            final scale = 1 - (_animationController.value / 0.20);
            return Stack(
              children: [
                const Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      'TEST',
                      style: TextStyle(color: Colors.white, fontSize: 32.0),
                    ),
                  ],
                ),
                Transform(
                  transform: Matrix4.identity()
                    ..translate(slide)
                    ..scale(scale),
                  alignment: Alignment.centerLeft,
                  child: SizedBox.expand(
                    child: Container(
                      color:Colors.white,
                      margin: const EdgeInsets.only(top:50),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Row(
                            children: [
                              IconButton(
                                  onPressed: () {
                                  },
                                  icon: const Icon(Icons.menu)),
                              const Text('Appbar'),
                            ],
                          ),
                          const Text(
                            'TEXT',
                            style: TextStyle(color: Colors.black, fontSize: 32.0),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),

              ],
            );
          },
        ),
      ),
    );
  }

  void _onDragStart(DragStartDetails details) {
    final isDragOpenFromLeft = _animationController.isDismissed &&
        details.globalPosition.dx < minDragStartEdge;
    final isDragCloseFromRight = _animationController.isCompleted &&
        details.globalPosition.dx > maxDragStartEdge;
    _canBeDragged = isDragOpenFromLeft || isDragCloseFromRight;
  }

  void _onDragUpdate(DragUpdateDetails details) {
    if (_canBeDragged) {
      final delta = details.primaryDelta! / maxSlide;
      _animationController.value += delta;
    }
  }

  void _onDragEnd(DragEndDetails details) {
    if (_animationController.isDismissed || _animationController.isCompleted) {
      return;
    }
    if (details.velocity.pixelsPerSecond.dx.abs() >= 165.0) {
      final visualVelocity = details.velocity.pixelsPerSecond.dx /
          MediaQuery.of(context).size.width;
      _animationController.fling(velocity: visualVelocity);
    } else if (_animationController.value < 0.5) {
      closeDrawer();
    } else {
      openDrawer();
    }
  }

  void openDrawer() {
    _animationController.forward();
  }

  void closeDrawer() {
    _animationController.reverse();
  }
}

字符串
我认为编辑这部分代码就足够了。

void _onDragStart(DragStartDetails details) {
    final isDragOpenFromLeft = _animationController.isDismissed &&
        details.globalPosition.dx < minDragStartEdge;
    final isDragCloseFromRight = _animationController.isCompleted &&
        details.globalPosition.dx > maxDragStartEdge;
    _canBeDragged = isDragOpenFromLeft || isDragCloseFromRight;
  }

busg9geu

busg9geu1#

这将照顾从右到左的过渡。_canBeDragged名称在这里有点混乱,但无论如何:

void _onDragUpdate(DragUpdateDetails details) {
    final delta = details.primaryDelta! / maxSlide;

    if (_canBeDragged) {
      _animationController.value += delta;
    } else {
      _animationController.value -= delta;
    }
  }

字符串
在动画中有意义的其他更改:

void _onDragEnd(DragEndDetails details) {
    if (_animationController.isDismissed || _animationController.isCompleted) {
      return;
    }

    if (_animationController.value < 0.3) {
      closeDrawer();
    } else {
      openDrawer();
    }
  }


此外,我会交换ScaffoldGestureDetector,以便当抽屉被打开时,整个屏幕听取拖动。

gcuhipw9

gcuhipw92#

要允许从右到左的拖放,需要修改_onDragStart方法以考虑两个方向。下面是_onDragStart方法的更新代码,它允许反向拖放:

void _onDragStart(DragStartDetails details) {
  final isDragOpenFromLeft = _animationController.isDismissed &&
      details.globalPosition.dx < minDragStartEdge;
  final isDragCloseFromRight = _animationController.isCompleted &&
      details.globalPosition.dx > maxDragStartEdge;
  _canBeDragged = isDragOpenFromLeft || isDragCloseFromRight;
  if (_animationController.isCompleted && details.globalPosition.dx < minDragStartEdge) {
    _canBeDragged = true;
    _animationController.reverse();
  }
}

字符串
在这个更新的_onDragStart方法中,我们首先检查用户是否从左侧开始拖动,如果是,则将_canBeDragged设置为true。此外,我们检查用户是否在抽屉打开时从右侧开始拖动(即_animationController.isCompleted),如果是这样,我们将_canBeDragged设置为true并反转动画以关闭抽屉。这将允许您从右向左拖动小部件以关闭抽屉。

iyr7buue

iyr7buue3#

您提供的代码允许从左到右拖动以显示底层小部件。要启用从右到左拖动以将顶部小部件移动到左侧,您需要进行一些调整。
下面是修改后的代码:

void _onDragStart(DragStartDetails details) {
    final isDragOpenFromLeft = _animationController.isDismissed &&
        details.globalPosition.dx < minDragStartEdge;
    final isDragCloseFromRight = _animationController.isCompleted &&
        details.globalPosition.dx > maxDragStartEdge;
    final isDragOpenFromRight = _animationController.isDismissed &&
        details.globalPosition.dx > maxDragStartEdge;
    final isDragCloseFromLeft = _animationController.isCompleted &&
        details.globalPosition.dx < minDragStartEdge;
    _canBeDragged = isDragOpenFromLeft || isDragCloseFromRight || isDragOpenFromRight || isDragCloseFromLeft;
  }

  void _onDragUpdate(DragUpdateDetails details) {
  if (_canBeDragged) {
    final delta = details.primaryDelta! / maxSlide;
    _animationController.value += delta;
  }
}

void _onDragEnd(DragEndDetails details) {
  if (_animationController.isDismissed || _animationController.isCompleted) {
    return;
  }
  final moveRight = details.velocity.pixelsPerSecond.dx > 0;
  if (moveRight) {
    if (details.velocity.pixelsPerSecond.dx.abs() >= 165.0) {
      final visualVelocity = details.velocity.pixelsPerSecond.dx /
          MediaQuery.of(context).size.width;
      _animationController.fling(velocity: visualVelocity);
    } else if (_animationController.value < 0.5) {
      closeDrawer();
    } else {
      openDrawer();
    }
  } else {
    if (details.velocity.pixelsPerSecond.dx.abs() >= 165.0) {
      final visualVelocity = details.velocity.pixelsPerSecond.dx /
          MediaQuery.of(context).size.width;
      _animationController.fling(velocity: visualVelocity);
    } else if (_animationController.value > 0.5) {
      openDrawer();
    } else {
      closeDrawer();
    }
  }
}

字符串

相关问题