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

问题描述 投票:0回答:2

在此处提供的完整代码中,来自

drag-and-drop
left to right
工作完美,允许我显示底层小部件。现在,我要介绍的更改是如何将
drag-and-drop
中的
right to left
添加到其中,这样我就可以将顶部小部件移动到左侧。

我的意思是,如何给它添加从右到左的反向拖放操作?

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;
  }
flutter dart flutter-animation
2个回答
0
投票

这将处理从右到左的过渡。 _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();
    }
  }

此外,我会将

Scaffold
GestureDetector
交换,这样当抽屉打开时,整个屏幕都会监听拖动。


0
投票

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

这是修改后的代码:

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();
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.