实现:会玩海龟汤页面组件的拖动效果

63 阅读1分钟
import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(home: PhysicsCardDragDemo()));
}

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

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    return Scaffold(
      appBar: AppBar(),
      body: DraggableCard(
        child: Container(
          width: size.width * 0.8,
          height: size.height * 0.8 / 3,
          child: Card(
            child: ListTile(title: Text("海龟汤"), subtitle: Text("汤面")),
          ),
        ),
      ), // FlutterLogo FlutterLogo(size: 64)
    );
  }
}

// 一个支持拖拽的卡片
class DraggableCard extends StatefulWidget {
  const DraggableCard({required this.child, super.key});

  final Widget child;

  @override
  State<DraggableCard> createState() => _DraggableCardState();
}

class _DraggableCardState extends State<DraggableCard>
    with SingleTickerProviderStateMixin {
  Alignment _dragAlignment = Alignment.center; // 卡片的对齐方式

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

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    return GestureDetector(
      // 当用户按下时,停止动画
      onPanDown: (details) {},
      // 当用户拖动时,更新卡片位置
      onPanUpdate: (details) {
        setState(() {
          Alignment next =
              _dragAlignment +
              Alignment(
                0, //details.delta.dx / (size.width / 2),
                details.delta.dy / (size.height / 2),
              );
          // 限制拖动范围在 [-0.8, 0.8]
          _dragAlignment = Alignment(
            0, //next.x.clamp(-0.8, 0.8),
            next.y.clamp(-0.8, 0.8),
          );
        });
      },
      onPanEnd: (details) {},
      child: Align(alignment: _dragAlignment, child: widget.child),
    );
  }
}

效果:

20250820_104704-ezgif.com-video-to-gif-converter.gif