Created
October 21, 2020 01:02
-
-
Save RedBrogdon/516c310a7c7d0c6fea90fcb8d26feec2 to your computer and use it in GitHub Desktop.
Draggable animation (null safe)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter/physics.dart'; | |
main() { | |
runApp( | |
MaterialApp( | |
debugShowCheckedModeBanner: false, | |
home: PhysicsCardDragDemo(), | |
), | |
); | |
} | |
class PhysicsCardDragDemo extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text('A draggable card!'), | |
), | |
body: DraggableCard( | |
child: FlutterLogo( | |
size: 128, | |
), | |
), | |
); | |
} | |
} | |
class DraggableCard extends StatefulWidget { | |
final Widget child; | |
DraggableCard({required this.child}); | |
@override | |
_DraggableCardState createState() => _DraggableCardState(); | |
} | |
class _DraggableCardState extends State<DraggableCard> | |
with SingleTickerProviderStateMixin { | |
late final _controller = AnimationController(vsync: this); | |
Alignment _dragAlignment = Alignment.center; | |
Animation<Alignment>? _animation; | |
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 | |
void initState() { | |
super.initState(); | |
_controller.addListener(() { | |
setState(() { | |
_dragAlignment = _animation?.value ?? Alignment.center; | |
}); | |
}); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
final size = MediaQuery.of(context)?.size ?? Size(100, 100); | |
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, | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment