Flutter笔记-回弹动画

207 阅读1分钟

这一节主要了解一下Flutter中的回弹动画,实现这一过程主要分如下几步: `

  1. 创建一个动画控制器
  2. 使用手势移动 widget
  3. 对 widget 进行动画
  4. 计算速度以模拟弹跳运动 `

栗子如下:

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

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

```
class DragAnimationDemo extends StatelessWidget {

  const DragAnimationDemo({super.key});


  @override
  Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(),
     body: const DraggableCard(child: FlutterLogo(size: 128,)),
   );
  }

}
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{
  
  late AnimationController  _controller;
  
  Alignment _dragAlignment = Alignment.center;
  late Animation<Alignment> _animation;
  
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _controller = AnimationController(vsync: this);
    _controller.addListener(() { 
      setState(() {
        _dragAlignment = _animation.value;
      });
    });
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  void _runAnimation(Offset pixelsPerSecond,Size size) {
    _animation = _controller.drive(
      AlignmentTween(begin: _dragAlignment,end: Alignment.center)
    );
    final unitsPerSecondX = pixelsPerSecond.dx/size.width;
    final unitsPerSecondY = pixelsPerSecond.dy/size.height;
    final unitsPerSecond = Offset(unitsPerSecondX, unitsPerSecondY);
    final unitVelocity = unitsPerSecond.distance;
    
    const spring = SpringDescription(mass: 30
        , stiffness: 1, damping: 1);
    final simulation = SpringSimulation(spring, 0, 1, -unitVelocity);
    _controller.animateWith(simulation);
    
  }
  
  
  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    return GestureDetector(
      onPanDown: (details) {
        _controller.stop();
      },
      onPanUpdate: (details) {
        setState(() {
          _dragAlignment += Alignment(
            details.delta.dx/(size.width/2),
            details.delta.dy / (size.height/2)
          );
        });
      },
      onPanEnd: (details) {
        _runAnimation(details.velocity.pixelsPerSecond,size);
      },
      child: Align(
        alignment: _dragAlignment,
        child: Card(
          child: widget.child,
        ),
      ),
    );
  }
  
}