mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
Flutter 3.29 beta (#2571)
This commit is contained in:
@@ -27,11 +27,13 @@ void setupWindow() {
|
||||
setWindowMinSize(const Size(windowWidth, windowHeight));
|
||||
setWindowMaxSize(const Size(windowWidth, windowHeight));
|
||||
getCurrentScreen().then((screen) {
|
||||
setWindowFrame(Rect.fromCenter(
|
||||
center: screen!.frame.center,
|
||||
width: windowWidth,
|
||||
height: windowHeight,
|
||||
));
|
||||
setWindowFrame(
|
||||
Rect.fromCenter(
|
||||
center: screen!.frame.center,
|
||||
width: windowWidth,
|
||||
height: windowHeight,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -41,11 +43,7 @@ class Demo {
|
||||
final String route;
|
||||
final WidgetBuilder builder;
|
||||
|
||||
const Demo({
|
||||
required this.name,
|
||||
required this.route,
|
||||
required this.builder,
|
||||
});
|
||||
const Demo({required this.name, required this.route, required this.builder});
|
||||
}
|
||||
|
||||
final basicDemos = [
|
||||
@@ -182,9 +180,7 @@ class AnimationSamples extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp.router(
|
||||
title: 'Animation Samples',
|
||||
theme: ThemeData(
|
||||
colorSchemeSeed: Colors.deepPurple,
|
||||
),
|
||||
theme: ThemeData(colorSchemeSeed: Colors.deepPurple),
|
||||
routerConfig: router,
|
||||
);
|
||||
}
|
||||
@@ -197,9 +193,7 @@ class HomePage extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final headerStyle = Theme.of(context).textTheme.titleLarge;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Animation Samples'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Animation Samples')),
|
||||
body: ListView(
|
||||
children: [
|
||||
ListTile(title: Text('Basics', style: headerStyle)),
|
||||
|
||||
@@ -24,8 +24,10 @@ class _AnimatedBuilderDemoState extends State<AnimatedBuilderDemo>
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = AnimationController(vsync: this, duration: duration);
|
||||
animation =
|
||||
ColorTween(begin: beginColor, end: endColor).animate(controller);
|
||||
animation = ColorTween(
|
||||
begin: beginColor,
|
||||
end: endColor,
|
||||
).animate(controller);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -37,9 +39,7 @@ class _AnimatedBuilderDemoState extends State<AnimatedBuilderDemo>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('AnimatedBuilder'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('AnimatedBuilder')),
|
||||
body: Center(
|
||||
// AnimatedBuilder handles listening to a given animation and calling the builder
|
||||
// whenever the value of the animation change. This can be useful when a Widget
|
||||
@@ -49,9 +49,7 @@ class _AnimatedBuilderDemoState extends State<AnimatedBuilderDemo>
|
||||
animation: animation,
|
||||
builder: (context, child) {
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: animation.value,
|
||||
),
|
||||
style: ElevatedButton.styleFrom(backgroundColor: animation.value),
|
||||
child: child,
|
||||
onPressed: () {
|
||||
switch (controller.status) {
|
||||
|
||||
@@ -49,9 +49,7 @@ class _AnimatedContainerDemoState extends State<AnimatedContainerDemo> {
|
||||
// the properties of a container. For example, you could use this to design expanding
|
||||
// and shrinking cards.
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('AnimatedContainer'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('AnimatedContainer')),
|
||||
body: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -71,9 +69,7 @@ class _AnimatedContainerDemoState extends State<AnimatedContainerDemo> {
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
child: const Text(
|
||||
'change',
|
||||
),
|
||||
child: const Text('change'),
|
||||
onPressed: () => change(),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -54,9 +54,7 @@ class _AnimationControllerDemoState extends State<AnimationControllerDemo>
|
||||
// when building child widgets. You can also check the status to see if the animation
|
||||
// has completed.
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Animation Controller'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Animation Controller')),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -79,7 +77,7 @@ class _AnimationControllerDemoState extends State<AnimationControllerDemo>
|
||||
controller.forward();
|
||||
}
|
||||
},
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class TypewriterTween extends Tween<String> {
|
||||
TypewriterTween({String begin = '', String end = ''})
|
||||
: super(begin: begin, end: end);
|
||||
: super(begin: begin, end: end);
|
||||
|
||||
@override
|
||||
String lerp(double t) {
|
||||
@@ -89,7 +89,9 @@ class _CustomTweenDemoState extends State<CustomTweenDemo>
|
||||
return Text(
|
||||
animation.value,
|
||||
style: const TextStyle(
|
||||
fontSize: 16, fontFamily: 'SpecialElite'),
|
||||
fontSize: 16,
|
||||
fontFamily: 'SpecialElite',
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -30,10 +30,7 @@ class _FadeTransitionDemoState extends State<FadeTransitionDemo>
|
||||
|
||||
_curve = CurvedAnimation(parent: _controller, curve: Curves.easeIn);
|
||||
|
||||
_animation = Tween(
|
||||
begin: 1.0,
|
||||
end: 0.0,
|
||||
).animate(_curve);
|
||||
_animation = Tween(begin: 1.0, end: 0.0).animate(_curve);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -45,29 +42,25 @@ class _FadeTransitionDemoState extends State<FadeTransitionDemo>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
'Fade Transition',
|
||||
),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Fade Transition')),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
FadeTransition(
|
||||
opacity: _animation,
|
||||
child: const Icon(
|
||||
Icons.star,
|
||||
color: Colors.amber,
|
||||
size: 300,
|
||||
),
|
||||
child: const Icon(Icons.star, color: Colors.amber, size: 300),
|
||||
),
|
||||
ElevatedButton(
|
||||
child: const Text('animate'),
|
||||
onPressed: () => setState(() {
|
||||
_controller.animateTo(1.0).then<TickerFuture>(
|
||||
(value) => _controller.animateBack(0.0));
|
||||
}),
|
||||
onPressed:
|
||||
() => setState(() {
|
||||
_controller
|
||||
.animateTo(1.0)
|
||||
.then<TickerFuture>(
|
||||
(value) => _controller.animateBack(0.0),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -11,9 +11,7 @@ class PageRouteBuilderDemo extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Page 1'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Page 1')),
|
||||
body: Center(
|
||||
child: ElevatedButton(
|
||||
child: const Text('Go!'),
|
||||
@@ -30,8 +28,10 @@ Route _createRoute() {
|
||||
return PageRouteBuilder<SlideTransition>(
|
||||
pageBuilder: (context, animation, secondaryAnimation) => _Page2(),
|
||||
transitionsBuilder: (context, animation, secondaryAnimation, child) {
|
||||
var tween =
|
||||
Tween<Offset>(begin: const Offset(0.0, 1.0), end: Offset.zero);
|
||||
var tween = Tween<Offset>(
|
||||
begin: const Offset(0.0, 1.0),
|
||||
end: Offset.zero,
|
||||
);
|
||||
var curveTween = CurveTween(curve: Curves.ease);
|
||||
|
||||
return SlideTransition(
|
||||
@@ -46,12 +46,12 @@ class _Page2 extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Page 2'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Page 2')),
|
||||
body: Center(
|
||||
child:
|
||||
Text('Page 2!', style: Theme.of(context).textTheme.headlineMedium),
|
||||
child: Text(
|
||||
'Page 2!',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -60,9 +60,7 @@ class _TweenSequenceDemoState extends State<TweenSequenceDemo>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Tween Sequences'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Tween Sequences')),
|
||||
body: Center(
|
||||
child: AnimatedBuilder(
|
||||
animation: animation,
|
||||
|
||||
@@ -40,27 +40,25 @@ class _TweenDemoState extends State<TweenDemo>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Tweens'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Tweens')),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 200),
|
||||
child: Text('\$${animation.value.toStringAsFixed(2)}',
|
||||
style: const TextStyle(fontSize: 24)),
|
||||
child: Text(
|
||||
'\$${animation.value.toStringAsFixed(2)}',
|
||||
style: const TextStyle(fontSize: 24),
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
child: Text(
|
||||
switch (controller.status) {
|
||||
AnimationStatus.completed => 'Buy a Mansion',
|
||||
AnimationStatus.forward => 'Accruing...',
|
||||
AnimationStatus.reverse => 'Spending...',
|
||||
_ => 'Win the lottery',
|
||||
},
|
||||
),
|
||||
child: Text(switch (controller.status) {
|
||||
AnimationStatus.completed => 'Buy a Mansion',
|
||||
AnimationStatus.forward => 'Accruing...',
|
||||
AnimationStatus.reverse => 'Spending...',
|
||||
_ => 'Win the lottery',
|
||||
}),
|
||||
onPressed: () {
|
||||
switch (controller.status) {
|
||||
case AnimationStatus.completed:
|
||||
@@ -69,7 +67,7 @@ class _TweenDemoState extends State<TweenDemo>
|
||||
controller.forward();
|
||||
}
|
||||
},
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -26,11 +26,11 @@ class _AnimatedListDemoState extends State<AnimatedListDemo> {
|
||||
void addUser() {
|
||||
setState(() {
|
||||
var index = listData.length;
|
||||
listData.add(
|
||||
UserModel(++_maxIdValue, 'New', 'Person'),
|
||||
listData.add(UserModel(++_maxIdValue, 'New', 'Person'));
|
||||
_listKey.currentState!.insertItem(
|
||||
index,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
);
|
||||
_listKey.currentState!
|
||||
.insertItem(index, duration: const Duration(milliseconds: 300));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -38,22 +38,22 @@ class _AnimatedListDemoState extends State<AnimatedListDemo> {
|
||||
setState(() {
|
||||
final index = listData.indexWhere((u) => u.id == id);
|
||||
var user = listData.removeAt(index);
|
||||
_listKey.currentState!.removeItem(
|
||||
index,
|
||||
(context, animation) {
|
||||
return FadeTransition(
|
||||
opacity: CurvedAnimation(
|
||||
parent: animation, curve: const Interval(0.5, 1.0)),
|
||||
child: SizeTransition(
|
||||
sizeFactor: CurvedAnimation(
|
||||
parent: animation, curve: const Interval(0.0, 1.0)),
|
||||
axisAlignment: 0.0,
|
||||
child: _buildItem(user),
|
||||
_listKey.currentState!.removeItem(index, (context, animation) {
|
||||
return FadeTransition(
|
||||
opacity: CurvedAnimation(
|
||||
parent: animation,
|
||||
curve: const Interval(0.5, 1.0),
|
||||
),
|
||||
child: SizeTransition(
|
||||
sizeFactor: CurvedAnimation(
|
||||
parent: animation,
|
||||
curve: const Interval(0.0, 1.0),
|
||||
),
|
||||
);
|
||||
},
|
||||
duration: const Duration(milliseconds: 600),
|
||||
);
|
||||
axisAlignment: 0.0,
|
||||
child: _buildItem(user),
|
||||
),
|
||||
);
|
||||
}, duration: const Duration(milliseconds: 600));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,9 +62,7 @@ class _AnimatedListDemoState extends State<AnimatedListDemo> {
|
||||
key: ValueKey<UserModel>(user),
|
||||
title: Text(user.firstName),
|
||||
subtitle: Text(user.lastName),
|
||||
leading: const CircleAvatar(
|
||||
child: Icon(Icons.person),
|
||||
),
|
||||
leading: const CircleAvatar(child: Icon(Icons.person)),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
onPressed: () => deleteUser(user.id),
|
||||
@@ -77,12 +75,7 @@ class _AnimatedListDemoState extends State<AnimatedListDemo> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('AnimatedList'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.add),
|
||||
onPressed: addUser,
|
||||
),
|
||||
],
|
||||
actions: [IconButton(icon: const Icon(Icons.add), onPressed: addUser)],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: AnimatedList(
|
||||
@@ -101,11 +94,7 @@ class _AnimatedListDemoState extends State<AnimatedListDemo> {
|
||||
}
|
||||
|
||||
class UserModel {
|
||||
UserModel(
|
||||
this.id,
|
||||
this.firstName,
|
||||
this.lastName,
|
||||
);
|
||||
UserModel(this.id, this.firstName, this.lastName);
|
||||
|
||||
final int id;
|
||||
final String firstName;
|
||||
|
||||
@@ -54,10 +54,12 @@ class _AnimatedPositionedDemoState extends State<AnimatedPositionedDemo> {
|
||||
left: leftPosition,
|
||||
duration: const Duration(seconds: 1),
|
||||
child: InkWell(
|
||||
onTap: () => changePosition(
|
||||
size.height -
|
||||
(appBar.preferredSize.height + topPadding + 50),
|
||||
size.width - 150),
|
||||
onTap:
|
||||
() => changePosition(
|
||||
size.height -
|
||||
(appBar.preferredSize.height + topPadding + 50),
|
||||
size.width - 150,
|
||||
),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
width: 150,
|
||||
|
||||
@@ -9,18 +9,18 @@ import 'package:flutter/material.dart';
|
||||
Color generateColor() => Color(0xFFFFFFFF & Random().nextInt(0xFFFFFFFF));
|
||||
|
||||
Widget generateContainer(int keyCount) => Container(
|
||||
key: ValueKey<int>(keyCount),
|
||||
height: Random().nextDouble() * 200,
|
||||
width: Random().nextDouble() * 200,
|
||||
decoration: BoxDecoration(
|
||||
color: generateColor(),
|
||||
borderRadius: BorderRadius.circular(Random().nextDouble() * 100),
|
||||
border: Border.all(
|
||||
color: generateColor(),
|
||||
width: Random().nextDouble() * 5,
|
||||
),
|
||||
),
|
||||
);
|
||||
key: ValueKey<int>(keyCount),
|
||||
height: Random().nextDouble() * 200,
|
||||
width: Random().nextDouble() * 200,
|
||||
decoration: BoxDecoration(
|
||||
color: generateColor(),
|
||||
borderRadius: BorderRadius.circular(Random().nextDouble() * 100),
|
||||
border: Border.all(
|
||||
color: generateColor(),
|
||||
width: Random().nextDouble() * 5,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
class AnimatedSwitcherDemo extends StatefulWidget {
|
||||
const AnimatedSwitcherDemo({super.key});
|
||||
@@ -48,9 +48,8 @@ class _AnimatedSwitcherDemoState extends State<AnimatedSwitcherDemo> {
|
||||
title: const Text('AnimatedSwitcher'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => setState(
|
||||
() => container = generateContainer(++keyCount),
|
||||
),
|
||||
onPressed:
|
||||
() => setState(() => container = generateContainer(++keyCount)),
|
||||
child: const Text('Change Widget'),
|
||||
),
|
||||
],
|
||||
@@ -62,10 +61,9 @@ class _AnimatedSwitcherDemoState extends State<AnimatedSwitcherDemo> {
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(seconds: 1),
|
||||
child: container,
|
||||
transitionBuilder: (child, animation) => ScaleTransition(
|
||||
scale: animation,
|
||||
child: child,
|
||||
),
|
||||
transitionBuilder:
|
||||
(child, animation) =>
|
||||
ScaleTransition(scale: animation, child: child),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -33,9 +33,7 @@ class _CardSwipeDemoState extends State<CardSwipeDemo> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Card Swipe'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Card Swipe')),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Center(
|
||||
@@ -100,8 +98,11 @@ class SwipeableCard extends StatefulWidget {
|
||||
final String imageAssetName;
|
||||
final VoidCallback onSwiped;
|
||||
|
||||
const SwipeableCard(
|
||||
{required this.onSwiped, required this.imageAssetName, super.key});
|
||||
const SwipeableCard({
|
||||
required this.onSwiped,
|
||||
required this.imageAssetName,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<SwipeableCard> createState() => _SwipeableCardState();
|
||||
@@ -118,10 +119,9 @@ class _SwipeableCardState extends State<SwipeableCard>
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController.unbounded(vsync: this);
|
||||
_animation = _controller.drive(Tween<Offset>(
|
||||
begin: Offset.zero,
|
||||
end: const Offset(1, 0),
|
||||
));
|
||||
_animation = _controller.drive(
|
||||
Tween<Offset>(begin: Offset.zero, end: const Offset(1, 0)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -179,17 +179,26 @@ class _SwipeableCardState extends State<SwipeableCard>
|
||||
}
|
||||
|
||||
void _updateAnimation(double dragPosition) {
|
||||
_animation = _controller.drive(Tween<Offset>(
|
||||
begin: Offset.zero,
|
||||
end: _isSwipingLeft ? const Offset(-1, 0) : const Offset(1, 0),
|
||||
));
|
||||
_animation = _controller.drive(
|
||||
Tween<Offset>(
|
||||
begin: Offset.zero,
|
||||
end: _isSwipingLeft ? const Offset(-1, 0) : const Offset(1, 0),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _animate({double velocity = 0}) {
|
||||
var description =
|
||||
const SpringDescription(mass: 50, stiffness: 1, damping: 1);
|
||||
var simulation =
|
||||
SpringSimulation(description, _controller.value, 1, velocity);
|
||||
var description = const SpringDescription(
|
||||
mass: 50,
|
||||
stiffness: 1,
|
||||
damping: 1,
|
||||
);
|
||||
var simulation = SpringSimulation(
|
||||
description,
|
||||
_controller.value,
|
||||
1,
|
||||
velocity,
|
||||
);
|
||||
_controller.animateWith(simulation).then<void>((_) {
|
||||
widget.onSwiped();
|
||||
});
|
||||
|
||||
@@ -21,9 +21,7 @@ class CarouselDemo extends StatelessWidget {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Carousel Demo'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Carousel Demo')),
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
@@ -79,30 +77,29 @@ class _CarouselState extends State<Carousel> {
|
||||
},
|
||||
controller: _controller,
|
||||
scrollBehavior: ScrollConfiguration.of(context).copyWith(
|
||||
dragDevices: {
|
||||
ui.PointerDeviceKind.touch,
|
||||
ui.PointerDeviceKind.mouse,
|
||||
},
|
||||
dragDevices: {ui.PointerDeviceKind.touch, ui.PointerDeviceKind.mouse},
|
||||
),
|
||||
itemBuilder: (context, index) => AnimatedBuilder(
|
||||
animation: _controller,
|
||||
builder: (context, child) {
|
||||
var result = _pageHasChanged ? _controller.page! : _currentPage * 1.0;
|
||||
itemBuilder:
|
||||
(context, index) => AnimatedBuilder(
|
||||
animation: _controller,
|
||||
builder: (context, child) {
|
||||
var result =
|
||||
_pageHasChanged ? _controller.page! : _currentPage * 1.0;
|
||||
|
||||
// The horizontal position of the page between a 1 and 0
|
||||
var value = result - index;
|
||||
value = (1 - (value.abs() * .5)).clamp(0.0, 1.0);
|
||||
// The horizontal position of the page between a 1 and 0
|
||||
var value = result - index;
|
||||
value = (1 - (value.abs() * .5)).clamp(0.0, 1.0);
|
||||
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
height: Curves.easeOut.transform(value) * size.height,
|
||||
width: Curves.easeOut.transform(value) * size.width,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: widget.itemBuilder(context, index),
|
||||
),
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
height: Curves.easeOut.transform(value) * size.height,
|
||||
width: Curves.easeOut.transform(value) * size.width,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: widget.itemBuilder(context, index),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,10 +46,7 @@ class _CurvedAnimationDemoState extends State<CurvedAnimationDemo>
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = AnimationController(
|
||||
duration: _duration,
|
||||
vsync: this,
|
||||
);
|
||||
controller = AnimationController(duration: _duration, vsync: this);
|
||||
selectedForwardCurve = curves[0];
|
||||
selectedReverseCurve = curves[0];
|
||||
curvedAnimation = CurvedAnimation(
|
||||
@@ -57,38 +54,35 @@ class _CurvedAnimationDemoState extends State<CurvedAnimationDemo>
|
||||
curve: selectedForwardCurve.curve,
|
||||
reverseCurve: selectedReverseCurve.curve,
|
||||
);
|
||||
animationRotation = Tween<double>(
|
||||
begin: 0,
|
||||
end: 2 * math.pi,
|
||||
).animate(curvedAnimation)
|
||||
..addListener(() {
|
||||
setState(() {});
|
||||
})
|
||||
..addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
controller.reverse();
|
||||
}
|
||||
});
|
||||
animationTranslation = Tween<Offset>(
|
||||
begin: const Offset(-1, 0),
|
||||
end: const Offset(1, 0),
|
||||
).animate(curvedAnimation)
|
||||
..addListener(() {
|
||||
setState(() {});
|
||||
})
|
||||
..addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
controller.reverse();
|
||||
}
|
||||
});
|
||||
animationRotation =
|
||||
Tween<double>(begin: 0, end: 2 * math.pi).animate(curvedAnimation)
|
||||
..addListener(() {
|
||||
setState(() {});
|
||||
})
|
||||
..addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
controller.reverse();
|
||||
}
|
||||
});
|
||||
animationTranslation =
|
||||
Tween<Offset>(
|
||||
begin: const Offset(-1, 0),
|
||||
end: const Offset(1, 0),
|
||||
).animate(curvedAnimation)
|
||||
..addListener(() {
|
||||
setState(() {});
|
||||
})
|
||||
..addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
controller.reverse();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Curved Animation'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Curved Animation')),
|
||||
body: Column(
|
||||
children: [
|
||||
const SizedBox(height: 20.0),
|
||||
@@ -97,10 +91,13 @@ class _CurvedAnimationDemoState extends State<CurvedAnimationDemo>
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
DropdownButton<CurveChoice>(
|
||||
items: curves.map((curve) {
|
||||
return DropdownMenuItem<CurveChoice>(
|
||||
value: curve, child: Text(curve.name));
|
||||
}).toList(),
|
||||
items:
|
||||
curves.map((curve) {
|
||||
return DropdownMenuItem<CurveChoice>(
|
||||
value: curve,
|
||||
child: Text(curve.name),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (newCurve) {
|
||||
if (newCurve != null) {
|
||||
setState(() {
|
||||
@@ -117,10 +114,13 @@ class _CurvedAnimationDemoState extends State<CurvedAnimationDemo>
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
DropdownButton<CurveChoice>(
|
||||
items: curves.map((curve) {
|
||||
return DropdownMenuItem<CurveChoice>(
|
||||
value: curve, child: Text(curve.name));
|
||||
}).toList(),
|
||||
items:
|
||||
curves.map((curve) {
|
||||
return DropdownMenuItem<CurveChoice>(
|
||||
value: curve,
|
||||
child: Text(curve.name),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (newCurve) {
|
||||
if (newCurve != null) {
|
||||
setState(() {
|
||||
@@ -134,18 +134,12 @@ class _CurvedAnimationDemoState extends State<CurvedAnimationDemo>
|
||||
const SizedBox(height: 35.0),
|
||||
Transform.rotate(
|
||||
angle: animationRotation.value,
|
||||
child: const Center(
|
||||
child: FlutterLogo(
|
||||
size: 100,
|
||||
),
|
||||
),
|
||||
child: const Center(child: FlutterLogo(size: 100)),
|
||||
),
|
||||
const SizedBox(height: 35.0),
|
||||
FractionalTranslation(
|
||||
translation: animationTranslation.value,
|
||||
child: const FlutterLogo(
|
||||
size: 100,
|
||||
),
|
||||
child: const FlutterLogo(size: 100),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
ElevatedButton(
|
||||
|
||||
@@ -11,12 +11,8 @@ class ExpandCardDemo extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Expandable Card'),
|
||||
),
|
||||
body: const Center(
|
||||
child: ExpandCard(),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Expandable Card')),
|
||||
body: const Center(child: ExpandCard()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -56,24 +52,23 @@ class _ExpandCardState extends State<ExpandCard>
|
||||
duration: duration,
|
||||
firstCurve: Curves.easeInOutCubic,
|
||||
secondCurve: Curves.easeInOutCubic,
|
||||
crossFadeState: selected
|
||||
? CrossFadeState.showSecond
|
||||
: CrossFadeState.showFirst,
|
||||
crossFadeState:
|
||||
selected
|
||||
? CrossFadeState.showSecond
|
||||
: CrossFadeState.showFirst,
|
||||
// Use Positioned.fill() to pass the constraints to its children.
|
||||
// This allows the Images to use BoxFit.cover to cover the correct
|
||||
// size
|
||||
layoutBuilder:
|
||||
(topChild, topChildKey, bottomChild, bottomChildKey) {
|
||||
layoutBuilder: (
|
||||
topChild,
|
||||
topChildKey,
|
||||
bottomChild,
|
||||
bottomChildKey,
|
||||
) {
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
key: bottomChildKey,
|
||||
child: bottomChild,
|
||||
),
|
||||
Positioned.fill(
|
||||
key: topChildKey,
|
||||
child: topChild,
|
||||
),
|
||||
Positioned.fill(key: bottomChildKey, child: bottomChild),
|
||||
Positioned.fill(key: topChildKey, child: topChild),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
||||
@@ -14,19 +14,15 @@ class FlutterAnimateDemo extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Flutter Animate Demo'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Flutter Animate Demo')),
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text(
|
||||
"Hello Flutter Animate",
|
||||
style: Theme.of(context).textTheme.headlineLarge,
|
||||
)
|
||||
.animate(
|
||||
onPlay: (controller) => controller.repeat(),
|
||||
"Hello Flutter Animate",
|
||||
style: Theme.of(context).textTheme.headlineLarge,
|
||||
)
|
||||
.animate(onPlay: (controller) => controller.repeat())
|
||||
.then(delay: 250.ms)
|
||||
.fadeIn(duration: 500.ms)
|
||||
.then(delay: 250.ms)
|
||||
|
||||
@@ -24,16 +24,15 @@ class Grid extends StatelessWidget {
|
||||
return Scaffold(
|
||||
body: GridView.builder(
|
||||
itemCount: 40,
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return (index >= 20)
|
||||
? const SmallCard(
|
||||
imageAssetName: 'assets/eat_cape_town_sm.jpg',
|
||||
)
|
||||
? const SmallCard(imageAssetName: 'assets/eat_cape_town_sm.jpg')
|
||||
: const SmallCard(
|
||||
imageAssetName: 'assets/eat_new_orleans_sm.jpg',
|
||||
);
|
||||
imageAssetName: 'assets/eat_new_orleans_sm.jpg',
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -46,14 +45,12 @@ Route _createRoute(BuildContext parentContext, String image) {
|
||||
return _SecondPage(image);
|
||||
},
|
||||
transitionsBuilder: (context, animation, secondaryAnimation, child) {
|
||||
var rectAnimation = _createTween(parentContext)
|
||||
.chain(CurveTween(curve: Curves.ease))
|
||||
.animate(animation);
|
||||
var rectAnimation = _createTween(
|
||||
parentContext,
|
||||
).chain(CurveTween(curve: Curves.ease)).animate(animation);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
PositionedTransition(rect: rectAnimation, child: child),
|
||||
],
|
||||
children: [PositionedTransition(rect: rectAnimation, child: child)],
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -65,10 +62,7 @@ Tween<RelativeRect> _createTween(BuildContext context) {
|
||||
var rect = box.localToGlobal(Offset.zero) & box.size;
|
||||
var relativeRect = RelativeRect.fromSize(rect, windowSize);
|
||||
|
||||
return RelativeRectTween(
|
||||
begin: relativeRect,
|
||||
end: RelativeRect.fill,
|
||||
);
|
||||
return RelativeRectTween(begin: relativeRect, end: RelativeRect.fill);
|
||||
}
|
||||
|
||||
class SmallCard extends StatelessWidget {
|
||||
@@ -84,10 +78,7 @@ class SmallCard extends StatelessWidget {
|
||||
var nav = Navigator.of(context);
|
||||
nav.push<void>(_createRoute(context, imageAssetName));
|
||||
},
|
||||
child: Image.asset(
|
||||
imageAssetName,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
child: Image.asset(imageAssetName, fit: BoxFit.cover),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -109,10 +100,7 @@ class _SecondPage extends StatelessWidget {
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: Image.asset(
|
||||
imageAssetName,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
child: Image.asset(imageAssetName, fit: BoxFit.cover),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -11,19 +11,16 @@ class HeroAnimationDemo extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Hero Animation'),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Hero Animation')),
|
||||
body: GestureDetector(
|
||||
child: Hero(
|
||||
tag: 'hero-page-child',
|
||||
child: _createHeroContainer(
|
||||
size: 50.0,
|
||||
color: Colors.grey.shade300,
|
||||
),
|
||||
child: _createHeroContainer(size: 50.0, color: Colors.grey.shade300),
|
||||
),
|
||||
onTap: () => Navigator.of(context).push<void>(
|
||||
MaterialPageRoute(builder: (context) => const HeroPage())),
|
||||
onTap:
|
||||
() => Navigator.of(context).push<void>(
|
||||
MaterialPageRoute(builder: (context) => const HeroPage()),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -40,10 +37,7 @@ class HeroPage extends StatelessWidget {
|
||||
body: Center(
|
||||
child: Hero(
|
||||
tag: 'hero-page-child',
|
||||
child: _createHeroContainer(
|
||||
size: 100.0,
|
||||
color: Colors.white,
|
||||
),
|
||||
child: _createHeroContainer(size: 100.0, color: Colors.white),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -59,10 +53,7 @@ StatelessWidget _createHeroContainer({
|
||||
width: size,
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
margin: size < 100.0 ? const EdgeInsets.all(10.0) : const EdgeInsets.all(0),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: color,
|
||||
),
|
||||
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
|
||||
child: const FlutterLogo(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,14 +12,8 @@ class PhysicsCardDragDemo extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Spring Physics'),
|
||||
),
|
||||
body: const DraggableCard(
|
||||
child: FlutterLogo(
|
||||
size: 128,
|
||||
),
|
||||
),
|
||||
appBar: AppBar(title: const Text('Spring Physics')),
|
||||
body: const DraggableCard(child: FlutterLogo(size: 128)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -67,14 +61,15 @@ class _DraggableCardState extends State<DraggableCard>
|
||||
/// Calculates and runs a [SpringSimulation]
|
||||
void _runAnimation(Offset velocity, Size size) {
|
||||
_animation = _controller.drive(
|
||||
AlignmentTween(
|
||||
begin: _dragAlignment,
|
||||
end: Alignment.center,
|
||||
),
|
||||
AlignmentTween(begin: _dragAlignment, end: Alignment.center),
|
||||
);
|
||||
|
||||
final simulation =
|
||||
SpringSimulation(_spring, 0, 1, _normalizeVelocity(velocity, size));
|
||||
final simulation = SpringSimulation(
|
||||
_spring,
|
||||
0,
|
||||
1,
|
||||
_normalizeVelocity(velocity, size),
|
||||
);
|
||||
|
||||
_controller.animateWith(simulation);
|
||||
}
|
||||
@@ -97,20 +92,17 @@ class _DraggableCardState extends State<DraggableCard>
|
||||
final size = MediaQuery.of(context).size;
|
||||
return GestureDetector(
|
||||
onPanStart: (details) => _controller.stop(canceled: true),
|
||||
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,
|
||||
),
|
||||
),
|
||||
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)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,10 @@ class _RepeatingAnimationDemoState extends State<RepeatingAnimationDemo>
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_controller =
|
||||
AnimationController(duration: const Duration(seconds: 2), vsync: this)
|
||||
..repeat(reverse: true);
|
||||
_controller = AnimationController(
|
||||
duration: const Duration(seconds: 2),
|
||||
vsync: this,
|
||||
)..repeat(reverse: true);
|
||||
|
||||
_borderRadius = BorderRadiusTween(
|
||||
begin: BorderRadius.circular(100.0),
|
||||
|
||||
Reference in New Issue
Block a user