reflect动画,Flutter Animations动画效果合集(全网最全)

CurvedAnimation(曲线动画)

Tween(补间动画/伸缩动画)

Loading加载动画(ProgressDialog)

Fade 渐入淡出动画

AnimatedBuilder(曲线动画)

StaggerAnimation(交错动画)

AnimatedSwitcher(切换动画)

1.CurvedAnimation(曲线动画)

效果图

574171669896?utm_campaign=haruki

曲线.gif

关键代码

import 'package:flutter/material.dart';

class CurvedAnimationPage extends StatefulWidget {

CurvedAnimationPage({Key key, this.title}) : super(key: key);

final String title;

@override

_CurvedAnimationState createState() => _CurvedAnimationState();

}

class _CurvedAnimationState extends State

with SingleTickerProviderStateMixin {

Animation animation;

AnimationController controller;

@override

void initState() {

super.initState();

controller = AnimationController(

duration: const Duration(milliseconds: 2000), vsync: this);

animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn)

..addStatusListener((status) {

if (status == AnimationStatus.completed) {

controller.reverse();

} else if (status == AnimationStatus.dismissed) {

controller.forward();

}

});

controller.forward();

}

dispose() {

controller.dispose();

super.dispose();

}

@override

Widget build(BuildContext context) {

return AnimatedLogo(animation: animation);

}

}

class AnimatedLogo extends AnimatedWidget {

// The Tweens are static because they don't change.

static final _opacityTween = Tween(begin: 0.1, end: 1.0);

static final _sizeTween = Tween(begin: 0.0, end: 300.0);

AnimatedLogo({Key key, Animation animation})

: super(key: key, listenable: animation);

Widget build(BuildContext context) {

final Animation animation = listenable;

return Scaffold(

appBar: AppBar(

title: Text("曲线动画"),

),

body: Center(

child: Opacity(

opacity: _opacityTween.evaluate(animation),

child: Container(

margin: EdgeInsets.symmetric(vertical: 10.0),

height: _sizeTween.evaluate(animation),

width: _sizeTween.evaluate(animation),

child: FlutterLogo(),

)),

));

}

}

parent参数传入一个Animation对象,比如AnimationController

curve传入传入的就是动画曲线的具体实现,Curves类中已经帮我们默认实现了很多常用的动画曲线,比如减速运动Curves.decelerate

Curves曲线 动画过程

linear 匀速的

decelerate 匀减速

ease 开始加速,后面减速

easeIn 开始慢,后面快

easeOut 开始快,后面慢

easeInOut 开始慢,然后加速,最后再减速

2.Tween(补间动画/伸缩动画)

效果图

574171669896?utm_campaign=haruki

补间动画.gif

在补间动画中,定义了开始点和结束点、时间线以及定义转换时间和速度的曲线。然后由框架计算如何从开始点过渡到结束点。

Animation 对象,是 Flutter 动画库中的核心类,插入用于引导动画的值。

Animation 对象知道当前动画的状态(如:动画是否开始,停止,前进或者后退),但对屏幕上显示的内容一无所知。

AnimationController 对象管理着 Animation。

CurvedAnimation 将动画定义成非线性运动的动画。

关键代码

import 'package:flutter/material.dart';

class TweenAnimation extends StatefulWidget {

TweenAnimation({Key key, this.title}) : super(key: key);

final String title;

@override

_TweenAnimationState createState() => _TweenAnimationState();

}

class _TweenAnimationState extends State

with SingleTickerProviderStateMixin {

Animation animation;

AnimationController controller;

@override

void initState() {

super.initState();

controller = AnimationController(

duration: const Duration(milliseconds: 2000), vsync: this);

animation = Tween(begin: 0.0, end: 300.0).animate(controller)

..addListener(() {

setState(() {

print(animation.value);

});

})

..addStatusListener((status) {

if (status == AnimationStatus.completed) {

controller.reverse();

} else if (status == AnimationStatus.dismissed) {

controller.forward();

}

});

controller.forward();

}

dispose() {

controller.dispose();

super.dispose();

}

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text("补间动画"),

),

body: Container(

margin: EdgeInsets.symmetric(vertical: 10.0),

height: animation.value,

width: animation.value,

child: FlutterLogo(),

));

}

}

3.Loading加载动画(ProgressDialog)

效果图

574171669896?utm_campaign=haruki

Loading.gif

关键代码

import 'package:flutter/material.dart';

import 'package:flutter_animations/progress_dialog.dart';

class LoadingPage extends StatefulWidget {

LoadingPage({Key key, this.title}) : super(key: key);

final String title;

@override

_LoadingState createState() => _LoadingState();

}

class _LoadingState extends State {

bool _loading = false;

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text("加载动画"),

),

body: ProgressDialog(

isLoading: _loading,

message: '正在加载...',

alpha: 0.35,

child: Center(

child: RaisedButton(

onPressed: () => _onRefresh(),

child: Text('显示加载动画'),

),

),

),

);

}

Future _onRefresh() async {

setState(() {

_loading = !_loading;

});

// 模拟耗时操作

await Future.delayed(Duration(seconds: 5), () {

setState(() {

_loading = !_loading;

});

});

}

}

4.Fade 渐入淡出动画

效果图

574171669896?utm_campaign=haruki

渐入淡出.gif

关键代码

import 'package:flutter/material.dart';

class Fade extends StatefulWidget {

Fade({Key key, this.title}) : super(key: key);

final String title;

@override

_FadeState createState() => _FadeState();

}

class _FadeState extends State {

bool _visible = true;

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text("渐入淡出动画"),

),

body: Center(

child: AnimatedOpacity(

opacity: _visible ? 1.0 : 0.0,

duration: Duration(milliseconds: 500),

child: FlutterLogo(

size: 100.0,

)),

),

floatingActionButton: FloatingActionButton(

onPressed: () {

setState(() {

_visible = !_visible;

});

},

tooltip: "Toggole Opacity",

child: Icon(Icons.flip),

),

);

}

}

5.AnimatedBuilder(曲线动画)

效果图

574171669896?utm_campaign=haruki

AnimatedBuilder.gif

创建动画的widget

Key key,

@required Listenable animation,

@required this.builder,

this.child,

animation:Animationcontroller //动画

child 动画作用的view

builder:每次controller值改变都会回到builder 重新生成view

关键代码

import 'package:flutter/material.dart';

class AnimatedBuilderPage extends StatefulWidget {

AnimatedBuilderPage({Key key, this.title}) : super(key: key);

final String title;

@override

_AnimatedBuilderState createState() => _AnimatedBuilderState();

}

class _AnimatedBuilderState extends State

with SingleTickerProviderStateMixin {

Animation animation;

AnimationController controller;

@override

void initState() {

super.initState();

controller = AnimationController(

duration: const Duration(milliseconds: 2000), vsync: this);

final CurvedAnimation curve =

CurvedAnimation(parent: controller, curve: Curves.bounceIn);

animation = Tween(begin: 0.0, end: 300.0).animate(curve)

..addStatusListener((status) {

if (status == AnimationStatus.completed) {

controller.reverse();

} else if (status == AnimationStatus.dismissed) {

controller.forward();

}

});

controller.forward();

}

dispose() {

controller.dispose();

super.dispose();

}

@override

Widget build(BuildContext context) {

return GrowTransition(child: LogoWidget(), animation: animation);

}

}

class LogoWidget extends StatelessWidget {

build(BuildContext context) {

return Container(

margin: EdgeInsets.symmetric(vertical: 10.0),

child: FlutterLogo(),

);

}

}

class GrowTransition extends StatelessWidget {

GrowTransition({this.child, this.animation});

final Widget child;

final Animation animation;

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text("曲线动画AnimatedBuilder实现"),

),

body: Center(

child: AnimatedBuilder(

animation: animation,

builder: (BuildContext context, Widget child) {

return Container(

height: animation.value,

width: animation.value,

child: child);

},

child: child),

),

);

}

}

6.StaggerAnimation(交错动画)

交错动画由序列或重叠的动画组成,

要创建交错动画,使用多个动画对象,

一个AnimationController控制所有动画。

每个动画对象在间隔期间指定动画。

效果图

574171669896?utm_campaign=haruki

StaggerAnimation.gif

关键代码

import 'package:flutter/material.dart';

import 'dart:async';

import 'package:flutter/scheduler.dart' show timeDilation;

class StaggerAnimation extends StatelessWidget {

StaggerAnimation({Key key, this.controller}):

opacity = Tween(

begin: 0.0,

end: 1.0,

).animate(

CurvedAnimation(

parent: controller,

curve: Interval(

0.0,

0.100,

curve: Curves.ease,

),

),

),

width = Tween(

begin: 50.0,

end: 150.0,

).animate(

CurvedAnimation(

parent: controller,

curve: Interval(

0.125,

0.250,

curve: Curves.ease,

),

),

),

height = Tween(begin: 50.0, end: 150.0).animate(

CurvedAnimation(

parent: controller,

curve: Interval(

0.250,

0.375,

curve: Curves.ease,

),

),

),

padding = EdgeInsetsTween(

begin: const EdgeInsets.only(bottom: 16.0),

end: const EdgeInsets.only(bottom: 75.0),

).animate(

CurvedAnimation(

parent: controller,

curve: Interval(

0.250,

0.375,

curve: Curves.ease,

),

),

),

borderRadius = BorderRadiusTween(

begin: BorderRadius.circular(4.0),

end: BorderRadius.circular(75.0),

).animate(

CurvedAnimation(

parent: controller,

curve: Interval(

0.375,

0.500,

curve: Curves.ease,

),

),

),

color = ColorTween(

begin: Colors.indigo[100],

end: Colors.orange[400],

).animate(

CurvedAnimation(

parent: controller,

curve: Interval(

0.500,

0.750,

curve: Curves.ease,

),

),

),

super(key: key);

final Animation controller;

final Animation opacity;

final Animation width;

final Animation height;

final Animation padding;

final Animation borderRadius;

final Animation color;

// This function is called each time the controller "ticks" a new frame.

// When it runs, all of the animation's values will have been

// updated to reflect the controller's current value.

Widget _buildAnimation(BuildContext context, Widget child) {

return Container(

padding: padding.value,

alignment: Alignment.bottomCenter,

child: Opacity(

opacity: opacity.value,

child: Container(

width: width.value,

height: height.value,

decoration: BoxDecoration(

color: color.value,

border: Border.all(

color: Colors.indigo[300],

width: 3.0,

),

borderRadius: borderRadius.value,

),

),

),

);

}

@override

Widget build(BuildContext context) {

return AnimatedBuilder(

builder: _buildAnimation,

animation: controller,

);

}

}

class StaggerDemo extends StatefulWidget {

@override

_StaggerDemoState createState() => _StaggerDemoState();

}

class _StaggerDemoState extends State

with TickerProviderStateMixin {

AnimationController _controller;

@override

void initState() {

super.initState();

_controller = AnimationController(

duration: const Duration(milliseconds: 2000), vsync: this);

}

@override

void dispose() {

_controller.dispose();

super.dispose();

}

Future _playAnimation() async {

try {

await _controller.forward().orCancel;

await _controller.reverse().orCancel;

} on TickerCanceled {

// the animation got canceled, probably because we were disposed

}

}

@override

Widget build(BuildContext context) {

timeDilation = 10.0; // 1.0 is normal animation speed.

return Scaffold(

appBar: AppBar(

title: const Text('Staggered Animation'),

),

body: GestureDetector(

behavior: HitTestBehavior.opaque,

onTap: () {

_playAnimation();

},

child: Center(

child: Container(

width: 300.0,

height: 300.0,

decoration: BoxDecoration(

color: Colors.black.withOpacity(0.1),

border: Border.all(

color: Colors.black.withOpacity(0.5),

),

),

child: StaggerAnimation(controller: _controller.view),

),

),

),

);

}

}

7.AnimatedSwitcher(切换动画)

实际开发中,我们经常会遇到切换UI元素的场景,比如Tab切换、路由切换。为了增强用户体验,通常在切换时都会指定一个动画,以使切换过程显得平滑。

效果图

574171669896?utm_campaign=haruki

切换动画.gif

关键代码

import 'package:flutter/material.dart';

class AnimatedSwitcherDemo extends StatefulWidget {

AnimatedSwitcherDemo({Key key, this.title}) : super(key: key);

final String title;

@override

_AnimatedSwitcherState createState() => _AnimatedSwitcherState();

}

class _AnimatedSwitcherState extends State

with SingleTickerProviderStateMixin {

IconData _actionIcon = Icons.favorite_border;

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text('点击中间的❤️'),

actions: [],

),

body: Center(

child: AnimatedSwitcher(

transitionBuilder: (child, anim) {

return ScaleTransition(child: child, scale: anim);

},

duration: Duration(milliseconds: 350),

child: IconButton(

iconSize: 100,

key: ValueKey(_actionIcon),

icon: Icon(

_actionIcon,

color: Colors.pink,

),

onPressed: () {

setState(

() {

if (_actionIcon == Icons.favorite_border)

_actionIcon = Icons.favorite;

else

_actionIcon = Icons.favorite_border;

},

);

},

),

),

),

);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值