일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- textstyle
- variable
- 코틀린
- Flutter
- text
- Android
- 크롤러
- Yocto
- set
- animation
- 다트
- map
- crawler
- 웹크롤러
- kotlin
- pushnamed
- 클래스
- 파이썬
- DART
- package
- Collection
- ML
- Class
- function
- 콜렉션
- 플러터
- List
- python
- 함수
- import
- Today
- Total
조용한 담장
Flutter : Animation 본문
Animation library
Flutter 의 animation system 을 구현한 animation library 을 살펴보자.
import package:flutter/animation.dart
flutter 는 animation 을 값의 변화와 시간을 통해 표현한다.
Flutter represents an animation as a value that changes over a given duration, and that value may be of any type.
animation 의 시작의 값이 0 이라면 끝나는 값이 100 이라는 수의 값으로 표현한다.
이 변화되는 값은 다양한 속성에 적용되어 그 변화에 따른 animation 을 만들어 낸다.
예를들어 opacity(불투명도) 값을 사용한다면 1.0 에서 0.0 으로 값이 변할수록 투명해지는 효과가 생기게 된다.
그리고 지정된 시간의 값(duration) 위에서 animation 을 구현해 낸다.
Animation class
animation 의 현재 값을 Animation class 로 표현한다.
Animation<T>
flutter 의 animation system 은 Animation class 를 기반으로 구성되어 있다.
T 타입의 값(value)을 가지고 있다. animation 의 현재를 표현하는 값 이다.
animation 의 현재 상태를 나타내는 status 를 가지고 있다.
AnimationStatus enum 타입으로 현재 animation 이 진행되고 있는 방향(forward, reverse), 상태(completed, dismissed) 등을 표현한다.
addListener, addStatusListener 을 통해 value 와 status 의 값의 변화를 알려주는 listener 를 등록할 수 있다.
Simple animation example
간단한 코드 구현을 통해 값의 변화를 통한 animation 동작을 살펴보자.
AnimatedOpacity 는 0.0 ~ 1.0 의 값의 범위로 위젯의 불투명도를 변경하여 animation 을 만들어 낸다.
"Fade Out" 버튼을 누르면 opacity 값이 0.0, "Face In" 버튼을 누르면 1.0 으로 값을 변경한다.
AnimatedOpacity 는 현재의 opacity 값이 변경된 값과 다른것을 감지하면 변경된 값으로 duration(1초) 시간위에서 animation 을 만들어 낸다.
AnimatedOpacity(
opacity: opacityValue,
duration: Duration(seconds: 1),
child: FlutterLogo(
size: 100.0,
),
),
opacity 로 지정된 opacityValue 값이 변경되면 duration 시간 동안 child 위젯에 animation 효과를 만든다.
class _MyHomePageState extends State<MyHomePage> {
var opacityValue = 1.0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Demo Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'AnimatedOpacity',
),
AnimatedOpacity(
opacity: opacityValue,
duration: Duration(seconds: 1),
child: FlutterLogo(
size: 100.0,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
child: Text("Fade In"),
onPressed: () => setState(() {
opacityValue = 1.0;
})),
RaisedButton(
child: Text("Fade Out"),
onPressed: () => setState(() {
opacityValue = 0.0;
})),
],
),
],
),
),
);
}
}
AnimatedOpacity 는 정해진 범위내에서 animation 을 만들어 주는 기능을 제공하지만 조금 더 복잡한 animation 을 만드려면 AnimationController 를 사용할 수 있다.
AnimationController
AnimationController({
double value, Duration duration, Duration reverseDuration, String debugLabel,
double lowerBound: 0.0, double upperBound: 1.0,
AnimationBehavior animationBehavior: AnimationBehavior.normal,
@required TickerProvider vsync})
Animation 이 abstract class 이고 AnimationController 는 그 구현자(implementer) 중 하나 이다.
기본적으로 0.0 ~ 1.0 의 값의 범위를 가지고 아래와 같은 기능을 지원한다.
- animation 을 앞(forward), 뒤로(reverse) 재생하거나 멈출(stop) 수 있다.
- animation 에 특정 값을 지정할 수 있다.
- animation 의 upperBound 와 lowerBound 값을 지정할 수 있다.
- physics simulation 을 사용하여 fling animation effect 를 만들 수 있다.
Animation 의 implementer 인 CurvedAnimation 을 사용하여 AnimationController 를 사용해본 예제이다.
class _AnimationControllerPageState extends State<AnimationControllerPage> with SingleTickerProviderStateMixin {
Animation<double> _animation;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
);
_animation = CurvedAnimation(
parent: _controller,
curve: Curves.easeIn,
);
_animation.addListener(() {
setState(() {
});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
initState 에서 AnimationController 를 생성하고 CurvedAnimation 이 Curve 효과를 적용할 animation 대상을 parent 로 지정해 준다.
listener 를 추가하여 value 가 변경될 때 마다 UI 를 업데이트 하도록 한다.
사용이 완료되면 dispose 를 해줘야 한다.
Text(
'AnimationController value:${_animation.value.toStringAsFixed(2)}',
),
Container(
height: _animation.value*100,
width: _animation.value*100,
child: FlutterLogo(),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
child: Text("forward"),
onPressed: () => _controller.forward(),
),
RaisedButton(
child: Text("stop"),
onPressed: () => _controller.stop(),
),
RaisedButton(
child: Text("reverse"),
onPressed: () => _controller.reverse(),
),
],
),
Text 로 animation 의 value 를 출력한다.
value 값의 변화에 따라 Container 의 크기가 변하도록 값을 지정한다.
AnimationController 의 method 를 통해 animation 의 status 를 변경하는 버튼을 추가했다.
ImplicitlyAnimatedWidget and AnimatedWidget
다시 animation library 로 돌아가서 flutter 의 animation 위젯은 크게 ImplicitlyAnimatedWidget 과 AnimatedWidget 이 있다.
ImplicitlyAnimatedWidget 은 위의 예제에서 사용한 AnimatedOpacity 처럼 특정 속성값의 변경에 따라 animation 을 자동으로 만들어 주는 위젯이다.
widget tree 에 처음 추가되었을 때는 아무것도 안하고, 속성값이 변경되어 재빌드 되면 animation 을 만든다.
AnimationController 를 내부적으로 자동으로 만들어 animation 을 관리하므로 duration 과 curve 만 설정하여 간편하게 사용할 수 있다.
보통 위젯 "Foo" 의 implicitly animated widget 이라는 개념으로 "AnimatedFoo" 식으로 이름을 가진다.
AnimatedWidget 은 Listenable 위젯을 통해 값의 변화를 감지하여 재빌드 한다.
Listenable 은 보통 Animation 위젯이며 ChangeNotifier 나 ValueNotifier 도 사용할 수 있다.
AnimatedWidget 위젯들은 위 예제에서 사용한 AnimationController 을 통해 Animation 을 Listenable 위젯 으로써 argument 로 받고, 이를 통해 변화를 감지하여 animation 을 관리하게 되는 방식으로 많이 사용된다.
AnimationController 을 명시적으로 사용하므로 생성과 삭제또한 명시적으로 구현해 주어야 한다.
보통 "Foo" 위젯의 animated widget 이라는 개념으로 "FooTransition" 식으로 이름을 가진다.
ImplicitlyAnimatedWidget class
ImplicitlyAnimatedWidget({
Key key, Curve curve: Curves.linear,
@required Duration duration, VoidCallback onEnd})
-
AnimatedAlign, which is an implicitly animated version of Align.
-
AnimatedContainer, which is an implicitly animated version of Container.
-
AnimatedDefaultTextStyle, which is an implicitly animated version of DefaultTextStyle.
-
AnimatedOpacity, which is an implicitly animated version of Opacity.
-
AnimatedPadding, which is an implicitly animated version of Padding.
-
AnimatedPhysicalModel, which is an implicitly animated version of PhysicalModel.
-
AnimatedPositioned, which is an implicitly animated version of Positioned.
-
AnimatedPositionedDirectional, which is an implicitly animated version of PositionedDirectional.
-
AnimatedTheme, which is an implicitly animated version of Theme.
-
TweenAnimationBuilder, which animates any property expressed by a Tween to a specified target value.
-
AnimatedCrossFade, which cross-fades between two given children and animates itself between their sizes.
-
AnimatedSize, which automatically transitions its size over a given duration.
-
AnimatedSwitcher, which fades from one widget to another.
AnimatedAlign
AnimatedAlign({
Key key, @required AlignmentGeometry alignment, Widget child,
Curve curve: Curves.linear, @required Duration duration, VoidCallback onEnd})
AlignmentGeometry _alignment = Alignment.bottomLeft;
// ...
Container(
width: 200.0,
height: 200.0,
color: Colors.green[100],
padding: EdgeInsets.zero,
child: AnimatedAlign(
child: FlutterLogo(size: 100),
alignment: _alignment,
duration: Duration(seconds: 1),
curve: Curves.easeIn,
),
),
RaisedButton(
child: Text("AnimatedAlign Start"),
onPressed: () => setState(() {
_alignment = _alignment==Alignment.bottomLeft?Alignment.topRight:Alignment.bottomLeft;
}),
),
AnimatedContainer
AnimatedContainer({
Key key, AlignmentGeometry alignment, EdgeInsetsGeometry padding, Color color,
Decoration decoration, Decoration foregroundDecoration,
double width, double height,
BoxConstraints constraints, EdgeInsetsGeometry margin, Matrix4 transform,
Widget child, Curve curve: Curves.linear,
@required Duration duration, VoidCallback onEnd})
bool _trigger = false;
// ...
Container(
color: Colors.green[100],
padding: EdgeInsets.zero,
child: AnimatedContainer(
width: _trigger ? 200.0 : 100.0,
height: _trigger ? 100.0 : 200.0,
child: FlutterLogo(size: 50),
alignment: _trigger ? Alignment.topCenter : Alignment.bottomCenter,
duration: Duration(seconds: 1),
curve: Curves.easeIn,
),
),
RaisedButton(
child: Text("AnimatedContainer Start"),
onPressed: () => setState(() {
_trigger = !_trigger;
}),
),
AnimatedDefaultTextStyle
AnimatedDefaultTextStyle({
Key key, @required Widget child, @required TextStyle style, TextAlign textAlign,
bool softWrap: true, TextOverflow overflow: TextOverflow.clip, int maxLines,
Curve curve: Curves.linear, @required Duration duration, VoidCallback onEnd})
bool _trigger = false;
TextStyle textStyle() {
return _trigger
? TextStyle(
color: Colors.blue,
fontWeight: FontWeight.w900,
fontSize: 20)
: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400,
fontSize: 30);
}
// ...
Container(
padding: EdgeInsets.zero,
child: AnimatedDefaultTextStyle(
child: Text("Default Text Style"),
style: textStyle(),
duration: Duration(seconds: 1),
curve: Curves.easeIn,
),
),
RaisedButton(
child: Text("AnimatedDefaultTextStyle Start"),
onPressed: () => setState(() {
_trigger = !_trigger;
}),
),
AnimatedPadding
AnimatedPadding({
Key key, @required EdgeInsetsGeometry padding, Widget child,
Curve curve: Curves.linear, @required Duration duration, VoidCallback onEnd})
bool _trigger = false;
// ...
Container(
width: 100.0,
height: 100.0,
color: Colors.red,
child: AnimatedPadding(
child: Container(
color: Colors.black,
),
padding: _trigger
? EdgeInsets.all(5.0)
: EdgeInsets.symmetric(horizontal: 30.0, vertical: 10.0),
duration: Duration(seconds: 1),
curve: Curves.easeIn,
),
),
RaisedButton(
child: Text("AnimatedPadding Start"),
onPressed: () => setState(() {
_trigger = !_trigger;
}),
),
AnimatedPhysicalModel
AnimatedPhysicalModel({
Key key, @required Widget child, @required BoxShape shape,
Clip clipBehavior: Clip.none, BorderRadius borderRadius: BorderRadius.zero,
@required double elevation, @required Color color, bool animateColor: true,
@required Color shadowColor, bool animateShadowColor: true,
Curve curve: Curves.linear, @required Duration duration, VoidCallback onEnd})
bool _trigger = true;
//...
AnimatedPhysicalModel(
child: Container(
height: 100.0,
width: 100.0,
),
shape: BoxShape.rectangle,
borderRadius: _trigger ? BorderRadius.circular(20.0) : BorderRadius.zero,
elevation: _trigger ? 10.0 : 20.0,
color: _trigger? Colors.black : Colors.yellow,
shadowColor: _trigger? Colors.blue : Colors.red,
duration: Duration(seconds: 1),
curve: Curves.easeIn,
),
Container(height: 10.0,),
RaisedButton(
child: Text("AnimatedPhysicalModel Start"),
onPressed: () => setState(() {
_trigger = !_trigger;
}),
),
AnimatedPositioned
AnimatedPositioned({
Key key, @required Widget child,
double left, double top, double right, double bottom,
double width, double height,
Curve curve: Curves.linear, @required Duration duration, VoidCallback onEnd})
bool _trigger = true;
// ...
body: Stack(
alignment: Alignment.center,
children: <Widget>[
Positioned(
child: Text("Positioned"),
top: 10.0,
),
AnimatedPositioned(
child: Container(
color: Colors.blue,
),
top: _trigger ? 10.0 : 30.0,
height: _trigger ? 50.0 : 10.0,
width: 70.0,
duration: Duration(seconds: 1),
curve: Curves.easeIn,
),
],),),
AnimatedPositionedDirectional
AnimatedPositionedDirectional({
Key key, @required Widget child,
double start, double top, double end, double bottom, double width, double height,
Curve curve: Curves.linear, @required Duration duration, VoidCallback onEnd})
bool _trigger = true;
// ...
Stack(
alignment: Alignment.center,
children: <Widget>[
AnimatedPositionedDirectional(
child: Container(
child: Text("AnimatedPositionedDirectionalAnimatedPositionedDirectional"),
color: Colors.blue,
),
top: 50.0,
start: _trigger? 100.0 : 150.0,
end: _trigger ? 100.0 : 200.0,
height: _trigger ? 100.0 : 200.0,
duration: Duration(seconds: 1),
curve: Curves.easeIn,
),
],),
AnimatedTheme
AnimatedTheme({
Key key, @required ThemeData data, bool isMaterialAppTheme: false,
Curve curve: Curves.linear, Duration duration: kThemeAnimationDuration,
VoidCallback onEnd, @required Widget child})
bool _trigger = true;
// ...
AnimatedTheme(
data: _trigger ? ThemeData.light() : ThemeData.dark(),
child: Builder(
builder: (BuildContext context) {
return Container(
width: 100,
height: 100,
color: Theme.of(context).primaryColor,
);
},
),
),
AnimatedCrossFade
AnimatedCrossFade({
Key key, @required Widget firstChild, @required Widget secondChild,
Curve firstCurve: Curves.linear, Curve secondCurve: Curves.linear,
Curve sizeCurve: Curves.linear, AlignmentGeometry alignment: Alignment.topCenter,
@required CrossFadeState crossFadeState, @required Duration duration, Duration
reverseDuration, AnimatedCrossFadeBuilder layoutBuilder: defaultLayoutBuilder})
bool _trigger = true;
// ...
AnimatedCrossFade(
firstChild: FlutterLogo(style: FlutterLogoStyle.horizontal, size: 100.0),
secondChild: FlutterLogo(style: FlutterLogoStyle.stacked, size: 100.0),
crossFadeState: _trigger ? CrossFadeState.showFirst : CrossFadeState.showSecond,
duration: Duration(seconds: 1),
),
AnimatedWidget class
AnimatedWidget({Key key, @required Listenable listenable})
-
RotationTransition, which animates the rotation of a widget.
-
ScaleTransition, which animates the scale of a widget.
-
SizeTransition, which animates its own size.
-
FadeTransition, which is an animated version of Opacity.
-
SlideTransition, which animates the position of a widget relative to its normal position.
-
AlignTransition, which is an animated version of Align.
-
DecoratedBoxTransition, which is an animated version of DecoratedBox.
-
DefaultTextStyleTransition, which is an animated version of DefaultTextStyle.
-
PositionedTransition, which is an animated version of Positioned.
-
RelativePositionedTransition, which is an animated version of Positioned.
-
AnimatedBuilder, which is useful for complex animation use cases and a notable exception to the naming scheme of AnimatedWidget subclasses.
-
AnimatedModalBarrier, which is an animated version of ModalBarrier.
RotationTransition
RotationTransition({
Key key, @required Animation<double> turns,
Alignment alignment: Alignment.center, Widget child})
class _RotationTransitionPageState extends State<RotationTransitionPage>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
)..repeat(reverse: true);
_animation = CurvedAnimation(
parent: _controller,
curve: Curves.elasticInOut,
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('RotationTransition'),
),
body: Center(
child: Container(
child: RotationTransition(
turns: _animation,
child: FlutterLogo(size: 100,),
)
),
),
);
}
}
ScaleTransition
ScaleTransition({
Key key, @required Animation<double> scale,
Alignment alignment: Alignment.center, Widget child})
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
)..repeat(reverse: true);
_animation = CurvedAnimation(
parent: _controller,
curve: Curves.easeIn,
);
}
//...
ScaleTransition(
scale: _animation,
child: FlutterLogo(size: 100,),
)
SizeTransition
SizeTransition({
Key key, Axis axis: Axis.vertical, @required Animation<double> sizeFactor,
double axisAlignment: 0.0, Widget child})
SizeTransition(
sizeFactor: _animation,
axis: Axis.horizontal,
child: FlutterLogo(size: 100,),
)
FadeTransition
FadeTransition({
Key key, @required Animation<double> opacity,
bool alwaysIncludeSemantics: false, Widget child})
FadeTransition(
opacity: _animation,
child: FlutterLogo(size: 100,),
)
Animatable
위 AnimatedWidget 의 예제들은 Animation<double> 을 argument 로 사용한다.
Animatable 을 사용하여 Animation<T> 로 타입을 T 로 변경할 수 있다.
AnimationController 의 double 타입의 animation value 값을 다른 타입의 값의 범위로 변경시켜주는 동작을 한다.
예를 들어 0.0 ~ 1.0 범위의 값이 Color, Size 등의 다른 타입이 가지는 범위의 값으로 바꿔주는 것이다.
Animation<Offset> _offsetAnimation;
_offsetAnimation = Tween<Offset>(
begin: Offset.zero,
end: const Offset(1.5, 0.0),
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.elasticIn,
));
위의 예제는 Tween<Offset> 을 animate() 메소드를 통해 CurvedAnimation() 이 생성한 Animation<double> 의 타입을 변경해 Animation<Offset> 를 만들어 낸다.
Tween 은 Animatable 의 implementer 중 하나 이다.
Tweens
Tween({T begin, T end})
Tween 은 double 값 0.0 ~ 1.0 범위를 다른 타입의 시작(begin) 과 끝(end) 의 값으로 맵핑해주는 역할을 한다.
변경될 범위의 begin 과 end 를 지정해 줘야 한다.
위의 Animatable 예제 코드를 보면 0.0 ~ 1.0 이 Offset.zero ~ Offset(1.5, 0.0) 으로 맵핑된다.
Animation 이나 AnimationController 는 여러개의 Tween 을 가질 수 있다.
예를 들어 두개의 Tween 을 사용하여 크기와 색의 값이 동시에 변경되는 animation 를 생성할 수 있다.
TweenAnimationBuilder
TweenAnimationBuilder({
Key key, @required Tween<T> tween, @required Duration duration,
Curve curve: Curves.linear, @required ValueWidgetBuilder<T> builder,
VoidCallback onEnd, Widget child})
double targetValue = 24.0;
@override
Widget build(BuildContext context) {
return TweenAnimationBuilder(
tween: Tween<double>(begin: 0, end: targetValue),
duration: Duration(seconds: 1),
builder: (BuildContext context, double size, Widget child) {
return IconButton(
iconSize: size,
color: Colors.blue,
icon: child,
onPressed: () {
setState(() {
targetValue = targetValue == 24.0 ? 48.0 : 24.0;
});
},
);
},
child: Icon(Icons.aspect_ratio),
);
}
code from https://api.flutter.dev/flutter/widgets/TweenAnimationBuilder-class.html
TweenSequences
TweenSequence(List<TweenSequenceItem<T>> items)
TweenSequence 는 여러개의 Tween 을 연속적으로 수행되게 해준다.
TweenSequenceItem 이 한개의 TweenSequence 을 담는다.
class _TweenSequencePageState extends State<TweenSequencePage>
with SingleTickerProviderStateMixin {
Animation<double> _animation;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
);
_animation = TweenSequence(
<TweenSequenceItem<double>>[
TweenSequenceItem<double>(
tween: Tween<double>(begin: 5.0, end: 10.0)
.chain(CurveTween(curve: Curves.ease)),
weight: 40.0,
),
TweenSequenceItem<double>(
tween: ConstantTween<double>(10.0),
weight: 20.0,
),
TweenSequenceItem<double>(
tween: Tween<double>(begin: 10.0, end: 5.0)
.chain(CurveTween(curve: Curves.ease)),
weight: 40.0,
),
],
).animate(_controller);
_animation.addListener(() => setState(() {}));
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('TweenSequence'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ScaleTransition(
scale: _animation,
child: FlutterLogo(size: 10,),
),
SizedBox(height: 50.0,),
Text("animation value : ${_animation.value.toStringAsFixed(2)}"),
RaisedButton(
child: Text("TweenSequence Start"),
onPressed: () => _controller.forward(),
)
],
)
),
);
}
}
AnimatedWidget examples
AlignTransition
AlignTransition({
Key key, @required Animation<AlignmentGeometry> alignment,
@required Widget child, double widthFactor, double heightFactor})
AlignmentGeometryTween _animation;
//...
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
)..repeat(reverse: true);
_animation = AlignmentGeometryTween(
begin: Alignment.bottomLeft,
end: Alignment.topRight,
);
}
//...
AlignTransition(
alignment: _animation.animate(_controller),
child: FlutterLogo(size: 100,),
),
DecoratedBoxTransition
DecoratedBoxTransition({
Key key, @required Animation<Decoration> decoration,
DecorationPosition position: DecorationPosition.background,
@required Widget child})
DecorationTween _animation;
_animation = DecorationTween(
begin: BoxDecoration(
color: Colors.white,
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey,
blurRadius: 10.0,
spreadRadius: 4.0,
)
],
),
end: BoxDecoration(
color: Colors.white,
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey,
blurRadius: 2.0,
spreadRadius: 2.0,
)
],
borderRadius: BorderRadius.circular(12),
),
);
//...
DecoratedBoxTransition(
decoration: _animation.animate(_controller),
child: Container(
child: FlutterLogo(
size: 100.0,
),
),
),
DefaultTextStyleTransition
DefaultTextStyleTransition({
Key key, @required Animation<TextStyle> style, @required Widget child,
TextAlign textAlign, bool softWrap: true,
TextOverflow overflow: TextOverflow.clip, int maxLines})
TextStyleTween _animation;
_animation = TextStyleTween(
begin: TextStyle(
color: Colors.blue,
fontSize: 10.0,
fontStyle: FontStyle.italic,
),
end: TextStyle(
color: Colors.blueGrey,
fontSize: 20.0,
fontWeight: FontWeight.bold,
)
);
//...
DefaultTextStyleTransition(
style: _animation.animate(_controller),
child: Text("DefaultTextStyleTransition"),
),
PositionedTransition
PositionedTransition({
Key key, @required Animation<RelativeRect> rect, @required Widget child})
RelativeRectTween _animation;
_animation = RelativeRectTween(
begin: RelativeRect.fromLTRB(0.0, 0.0, 50.0, 50.0),
end: RelativeRect.fromLTRB(50.0, 50.0, 0.0, 0.0),
);
//...
Stack(
children: <Widget>[
PositionedTransition(
rect: _animation.animate(_controller),
child: FlutterLogo(size: 50.0,),
),
],
),
RelativePositionedTransition
RelativePositionedTransition({
Key key, @required Animation<Rect> rect, @required Size size,
@required Widget child})
RectTween _animation;
_animation = RectTween(
begin: Rect.fromLTRB(0.0, 0.0, 0.0, 0.0),
end: Rect.fromLTRB(50.0, 50.0, 50.0, 50.0),
);
//...
Stack(
children: <Widget>[
RelativePositionedTransition(
rect: _animation.animate(_controller),
size: Size(50.0, 50.0),
child: FlutterLogo(),
),
],
),
AnimatedBuilder
AnimatedBuilder({
Key key, @required Listenable animation,
@required TransitionBuilder builder, Widget child})
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
child: Container(
width: 200.0,
height: 200.0,
color: Colors.green,
child: const Center(
child: Text('Wee'),
),
),
builder: (BuildContext context, Widget child) {
return Transform.rotate(
angle: _controller.value * 2.0 * math.pi,
child: child,
);
},
);
}
code from https://api.flutter.dev/flutter/widgets/AnimatedBuilder-class.html
Animation Architecture
https://flutter.dev/docs/development/ui/animations/overview#architecture
Animation - AnimationController - SignleTickerProviderStateMixin - Ticker - SchedulerBinding - scheduleFrameCallback()
Reference
Introduction to animations - flutter.dev
Implicit animations - flutter.dev
'Flutter' 카테고리의 다른 글
Flutter: Staggered Animations (0) | 2020.02.19 |
---|---|
Flutter: Hero (0) | 2020.02.12 |
플러터 프로젝트 코멘트 지우기 (remove comments) (0) | 2020.01.28 |
[플러터] Flutter 1.12 release (0) | 2019.12.12 |
Flutter : Custom font (0) | 2019.11.20 |