mirror of
https://github.com/flutter/samples.git
synced 2025-11-09 06:18:49 +00:00
Add scroll physics demo (#123)
* add spring physics card demo * fix button colors in animations project * code review updates * refactor method into runAnimation * combine updateAnimation and runAnimation * update comment
This commit is contained in:
@@ -14,6 +14,7 @@ import 'src/misc/card_swipe.dart';
|
|||||||
import 'src/misc/carousel.dart';
|
import 'src/misc/carousel.dart';
|
||||||
import 'src/misc/expand_card.dart';
|
import 'src/misc/expand_card.dart';
|
||||||
import 'src/misc/focus_image.dart';
|
import 'src/misc/focus_image.dart';
|
||||||
|
import 'src/misc/physics_card_drag.dart';
|
||||||
import 'src/misc/repeating_animation.dart';
|
import 'src/misc/repeating_animation.dart';
|
||||||
|
|
||||||
void main() => runApp(AnimationSamples());
|
void main() => runApp(AnimationSamples());
|
||||||
@@ -48,6 +49,8 @@ final miscDemos = [
|
|||||||
Demo('Card Swipe', CardSwipeDemo.routeName, (context) => CardSwipeDemo()),
|
Demo('Card Swipe', CardSwipeDemo.routeName, (context) => CardSwipeDemo()),
|
||||||
Demo('Repeating Animation', RepeatingAnimationDemo.routeName,
|
Demo('Repeating Animation', RepeatingAnimationDemo.routeName,
|
||||||
(context) => RepeatingAnimationDemo()),
|
(context) => RepeatingAnimationDemo()),
|
||||||
|
Demo('Spring Physics', PhysicsCardDragDemo.routeName,
|
||||||
|
(context) => PhysicsCardDragDemo()),
|
||||||
];
|
];
|
||||||
|
|
||||||
final basicDemoRoutes =
|
final basicDemoRoutes =
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ class PageRouteBuilderDemo extends StatelessWidget {
|
|||||||
body: Center(
|
body: Center(
|
||||||
child: RaisedButton(
|
child: RaisedButton(
|
||||||
child: Text('Go!'),
|
child: Text('Go!'),
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).push(_createRoute());
|
Navigator.of(context).push(_createRoute());
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -43,12 +43,13 @@ class _CustomTweenDemoState extends State<CustomTweenDemo>
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
actions: [
|
actions: [
|
||||||
RaisedButton(
|
MaterialButton(
|
||||||
child: Text(
|
child: Text(
|
||||||
controller.status == AnimationStatus.completed
|
controller.status == AnimationStatus.completed
|
||||||
? 'Delete Essay'
|
? 'Delete Essay'
|
||||||
: 'Write Essay',
|
: 'Write Essay',
|
||||||
),
|
),
|
||||||
|
textColor: Colors.white,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (controller.status == AnimationStatus.completed) {
|
if (controller.status == AnimationStatus.completed) {
|
||||||
controller.reverse();
|
controller.reverse();
|
||||||
|
|||||||
117
animations/lib/src/misc/physics_card_drag.dart
Normal file
117
animations/lib/src/misc/physics_card_drag.dart
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
// Copyright 2019 The Flutter team. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/physics.dart';
|
||||||
|
|
||||||
|
class PhysicsCardDragDemo extends StatelessWidget {
|
||||||
|
static const String routeName = '/misc/physics_card';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(),
|
||||||
|
body: DraggableCard(
|
||||||
|
child: FlutterLogo(
|
||||||
|
size: 128,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A draggable card that moves back to [Alignment.center] when it's
|
||||||
|
/// released.
|
||||||
|
class DraggableCard extends StatefulWidget {
|
||||||
|
final Widget child;
|
||||||
|
DraggableCard({this.child});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_DraggableCardState createState() => _DraggableCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DraggableCardState extends State<DraggableCard>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
AnimationController _controller;
|
||||||
|
|
||||||
|
/// The alignment of the card as it is dragged or being animated.
|
||||||
|
///
|
||||||
|
/// While the card is being dragged, this value is set to the values computed
|
||||||
|
/// in the GestureDetector onPanUpdate callback. If the animation is running,
|
||||||
|
/// this value is set to the value of the [_animation].
|
||||||
|
Alignment _dragAlignment = Alignment.center;
|
||||||
|
|
||||||
|
Animation<Alignment> _animation;
|
||||||
|
|
||||||
|
/// Calculates and runs a [SpringSimulation]
|
||||||
|
void _runAnimation(Offset pixelsPerSecond, Size size) {
|
||||||
|
_animation = _controller.drive(
|
||||||
|
AlignmentTween(
|
||||||
|
begin: _dragAlignment,
|
||||||
|
end: Alignment.center,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// Calculate the velocity relative to the unit interval, [0,1],
|
||||||
|
// used by the animation controller.
|
||||||
|
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 = AnimationController(vsync: this);
|
||||||
|
|
||||||
|
_controller.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
_dragAlignment = _animation.value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user