Slide 1

Slide 1 text

Flutter Animations First Step 2018/09/01 (౔) DevFest @konifar

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Kyash Inc.

Slide 4

Slide 4 text

yome.fm

Slide 5

Slide 5 text

My First Flutter app

Slide 6

Slide 6 text

Kyash͸౤͛મ΋Ͱ͖Δ ؆୯ʹܾࡁɾૹۚͰ͖Δ΢ΥϨοτΞϓϦɻ “39ԁ”ૹΔͱͪΐͬͱͨ͠Կ͔͕ى͜Δɻ https://goo.gl/C594Ri kyash_id : konifar

Slide 7

Slide 7 text

Flutter Animations

Slide 8

Slide 8 text

Useful Links - FlutterΞχϝʔγϣϯͷΫϥε΍֓೦ɺαϯϓϧͷઆ໌
 https://flutter.io/tutorials/animation/
 https://flutter.io/animations/ - গ͠ෳࡶͳάϥϑΞχϝʔγϣϯΛ࡞ΔνϡʔτϦΞϧ
 https://medium.com/flutter-io/zero-to-one-with-flutter-43b13fd7b354
 https://medium.com/flutter-io/zero-to-one-with-flutter-part-two- 5aa2f06655cb - ίʔυϥϘͰͷ؆୯ͳΞχϝʔγϣϯ࣮૷
 https://codelabs.developers.google.com/codelabs/flutter/index.html#6

Slide 9

Slide 9 text

Goal FlutterͷΞχϝʔγϣϯΛΩϟονΞοϓ͢ Δ࣌ʹɺυΩϡϝϯτ΍νϡʔτϦΞϧ͕ཧղ ͠΍͍͢Α͏ʹ֓೦Λβοͱཧղ͢Δɻ

Slide 10

Slide 10 text

࿩͢͜ͱ - ΞχϝʔγϣϯΛ࣮૷͢ΔجຊͷྲྀΕ - ࣮૷͢Δ࣌ͷΫϥεͷ໾ׂ

Slide 11

Slide 11 text

࿩͞ͳ͍͜ͱ - Ξχϝʔγϣϯ಺෦ͷ࣮૷ͷ࿩ - ෳࡶͳΞχϝʔγϣϯͷ࿩ - Gestureͱ૊Έ߹Θͤͨ৔߹ͷ࿩

Slide 12

Slide 12 text

ԡ͓͑ͯ͘͞΂͖ Ϋϥε

Slide 13

Slide 13 text

Basic classes 1. AnimationController 2. Tween 3. CurvedAnimation 4. AnimatedBuilder

Slide 14

Slide 14 text

͜ΕΒͷઆ໌Λ͢Δલʹ

Slide 15

Slide 15 text

ͦ΋ͦ΋Animationͱ͸ ʰҰఆ࣌ؒͰɺϏϡʔͷϓϩύςΟͷ஋ΛมԽ ͤ͞ɺඳը͢ΔҰ࿈ͷྲྀΕʱ
 ͬ͘͟Γݴ͏ͱɺύϥύϥ·Μ͕

Slide 16

Slide 16 text

ྫ͑͹ 2ඵؒʢҰఆ࣌ؒʣͰɺ width, heightʢϓϩύ ςΟʣͷ஋ΛมԽͤ͞ɺ ϑϨʔϜ͕ߋ৽͞ΕΔ͝ͱ ʹඳը͢Δɻ

Slide 17

Slide 17 text

ଞʹ΋ - colorΛม͑Ε͹৭͕มΘΔ - opacityΛม͑Ε͹ಁա౓͕มΘΔ - x,y࠲ඪΛม͑Ε͹Ҡಈ͢Δ - radiusΛม͑Ε͹˘͔Β˓ʹมΘΔ

Slide 18

Slide 18 text

Basic classes - AnimationController - ࣌ؒΛܾΊɺ։࢝ɾऴྃͳͲͷ੍ޚΛ͢Δ - Tween - มߋ͢Δ஋ͷൣғΛܾΊΔ - CurvedAnimation - ஋ͷมԽʹ؇ٸΛ͚ͭΔ - AnimatedBuilder - มԽͨ͠஋Λඳը͢Δ

Slide 19

Slide 19 text

Basic classes - AnimationController - 2000ms ͷ࣌ؒͰϦϐʔτ - Tween - 0~300 ͷ஋ - CurvedAnimation - Linearʢ౳଎ʣ - AnimatedBuilder - 1ඵؒʹ60ճ˘Λඳը

Slide 20

Slide 20 text

Basic classes - AnimationController - 2000ms ͷ࣌ؒͰϦϐʔτ - Tween - 0~300 ͷ஋ - CurvedAnimation - Linearʢ౳଎ʣ - AnimatedBuilder - 1ඵؒʹ60ճ˘Λඳը Required Optional

Slide 21

Slide 21 text

؆୯ͳΞχϝʔγϣϯΛ ͜ΕΒͷΫϥεΛͻͱͭͣͭ ࢖͍ͳ͕Βҭ͍͖ͯͯ·͢

Slide 22

Slide 22 text

1. AnimationController͚ͩͰ࡞ͬͯΈΔ 2. TweenΛ͔ͭ͏ 3. CurvedAnimationͰ؇ٸΛ͚ͭΔ 4. Animation෦෼ΛWidgetʹ੾Γग़͢ 5. AnimatedBuilderͰϦϑΝΫλϦϯά 6. ࿈ଓͨ͠ΞχϝʔγϣϯΛ࡞Δ

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

AnimationController ͚ͩͰ࡞ͬͯΈΔ

Slide 25

Slide 25 text

AnimationController - ΞχϝʔγϣϯΛ੍ޚ͢ΔඞਢΫϥε - AnimationΫϥεΛܧঝ - ϑϨʔϜ͝ͱʹ0.0 ~ 1.0ͷؒͷ஋Λੜ੒ - ը໘্Ͳ͏දࣔ͞ΕΔ͔͸஌Βͳ͍

Slide 26

Slide 26 text

͜ΕΛ࡞Δ ੨͍˘͕2ඵ͔͚ͯ 300.0ͷେ͖͞·Ͱ ֦େ͞ΕΔΞχϝʔγϣϯ

Slide 27

Slide 27 text

class BasicAnimationApp extends StatefulWidget { @override _BasicAnimationAppState createState() => new _BasicAnimationAppState(); } class _BasicAnimationAppState extends State { @override Widget build(BuildContext context) { return Center( child: Container( width: 300.0, height: 300.0, decoration: BoxDecoration( color: Colors.blue[400], ), ), ); } } void main() { runApp(BasicAnimationApp()); } Ξχϝʔγϣϯͳ͠

Slide 28

Slide 28 text

class BasicAnimationApp extends StatefulWidget { @override _BasicAnimationAppState createState() => new _BasicAnimationAppState(); } class _BasicAnimationAppState extends State { @override Widget build(BuildContext context) { return Center( child: Container( width: 300.0, height: 300.0, decoration: BoxDecoration( color: Colors.blue[400], ), ), ); } } void main() { runApp(BasicAnimationApp()); } Ξχϝʔγϣϯͳ͠ buildϝιουͷதͷ width, height ͕ 300ݻఆͳͷͰɺͨͩͷ੨͍˘͕දࣔ͞ΕΔ͚ͩɻ

Slide 29

Slide 29 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; @override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) ..addListener(() { setState(() { }); }) controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: controller.value * 300.0, height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } …

Slide 30

Slide 30 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; @override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) ..addListener(() { setState(() { }); }) controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: controller.value * 300.0, height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } … initState()ͷதͰɺ2000msͰಈ࡞͢Δ AnimationControllerΠϯελϯεΛੜ੒ɻ

Slide 31

Slide 31 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; @override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) ..addListener(() { setState(() { }); }) controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: controller.value * 300.0, height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } … Ξχϝʔγϣϯ࣌ͷແବͳඳըΛ๷͙ͨΊʹ ର৅ͷStateʹTickerProviderΛ࣮૷ͯ͠౉͢ɻ

Slide 32

Slide 32 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; @override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) ..addListener(() { setState(() { }); }) controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: controller.value * 300.0, height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } … initState()ͷதͰΞχϝʔγϣϯͷ։࢝ɻ දࣔͨ͠Β͙͢ʹಈ͖ग़͢ɻ

Slide 33

Slide 33 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; @override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) ..addListener(() { setState(() { }); }) controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: controller.value * 300.0, height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } … buildϝιουͷதͰɺcontroller.valueͷ஋Λ ࢖ͬͯWidgetπϦʔΛ࡞Δɻ controller.value͸0.0~1.0ͳͷͰɺ 300ഒͯ͠widthͱheightʹηοτ͢Δɻ

Slide 34

Slide 34 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; @override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) ..addListener(() { setState(() { }); }) controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: controller.value * 300.0, height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } … AnimationController͕஋Λੜ੒ ͢Δͨͼʹඳը͢ΔͨΊʹɺ ListenerΛηοτͯ͠setState() ΛݺͿɻ

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; .. @override dispose() { controller.dispose(); super.dispose(); } } dispose() Λ๨Εͣʹ dispose() ΛݺΜͰ͓͔ͳ͍ͱ ϝϞϦϦʔΫ͢ΔͷͰ஫ҙɻ

Slide 37

Slide 37 text

addStatusListener() - Ξχϝʔγϣϯͷεςʔλε͕มΘͬͨ࣌ʹ ݺ͹ΕΔListener - forwardʢਖ਼ํ޲ʹಈ͍͍ͯΔʣ - reverseʢ൓ରํ޲ʹಈ͍͍ͯΔʣ - completedʢforwardͰऴྃͨ͠ʣ - dismissedʢreverseͰऴྃͨ͠ʣ

Slide 38

Slide 38 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; @override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) ..addListener(() { setState(() { }); }) ..addStatusListener((status) { if (status == AnimationStatus.completed) { controller.reverse(); } else if (status == AnimationStatus.dismissed) { controller.forward(); } }); controller.forward(); } Ξχϝʔγϣϯ͕ऴΘͬͨΒ൓ରํ޲ʢreverseʣʹ ಈ͔ͯ͠ɺऴΘͬͨΒ·ͨ։࢝ʢforwardʣ͢Δɻ

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

timeDilationͰ଎౓Λมߋ - timeDilation = 2.0 Λ௥Ճ͢Δͱ
 1/2ͷ଎͞ͰΞχϝʔγϣϯ͢Δ - σόοάͰΞχϝʔγϣϯͷ଎౓Λมߋ͢Δ ͷʹศར

Slide 41

Slide 41 text

import 'package:flutter/scheduler.dart';
 
 class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; .. @override Widget build(BuildContext context) {
 timeDilation = 2.0; return Center( child: Container( width: controller.value * 300.0, height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } .. scheduler.dartΛimport͠ timeDilationʹ஋Ληοτ͢Δɻ

Slide 42

Slide 42 text

TweenΛ͔ͭ͏

Slide 43

Slide 43 text

Tween - ΞχϝʔγϣϯͰੜ੒͢Δ஋ʢ0.0 ~ 1.0ʣ Λଞͷ஋ʹม׵͢Δ - ઌ΄Ͳͷྫͩͱɺ0.0 ~ 300.0

Slide 44

Slide 44 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller;
 final _sizeTween = Tween(begin: 0.0, end: 300.0); @override initState() { super.initState(); controller = AnimationController( .. controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(controller), height: _sizeTween.evaluate(controller), // width: controller.value * 300.0, // height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } …

Slide 45

Slide 45 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller;
 final _sizeTween = Tween(begin: 0.0, end: 300.0); @override initState() { super.initState(); controller = AnimationController( .. controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(controller), height: _sizeTween.evaluate(controller), // width: controller.value * 300.0, // height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } … 0.0 ~ 300.0 Ͱ஋ΛมԽͤ͞ΔͨΊͷ doubleܕͷTweenΠϯελϯεΛੜ੒ɻ

Slide 46

Slide 46 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller;
 final _sizeTween = Tween(begin: 0.0, end: 300.0); @override initState() { super.initState(); controller = AnimationController( .. controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(controller), height: _sizeTween.evaluate(controller), // width: controller.value * 300.0, // height: controller.value * 300.0, decoration: BoxDecoration(color: Colors.blue[400]), ), ); } … buildϝιουͰWidgetΛ૊ΈཱͯΔࡍʹ Tween͔Β0.0 ~ 300.0ͷ஋Λड͚औΕΔɻ

Slide 47

Slide 47 text

͞·͟·ͳ Tween - ColorTween - SizeTween - RectTween - BorderRadiusTween - DecorationTween - BoxConstraintsTween - https://docs.flutter.io/flutter/animation/Tween-class.html

Slide 48

Slide 48 text

ColorTween ੨͔ΒԫʹมԽ͢Δ ΞχϝʔγϣϯΛ௥Ճɻ

Slide 49

Slide 49 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller;
 final _sizeTween = Tween(begin: 0.0, end: 300.0); final _colorTween = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]); @override initState() { super.initState(); controller = AnimationController( .. controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(controller), height: _sizeTween.evaluate(controller), decoration: BoxDecoration(color: Colors.blue[400]), // decoration: BoxDecoration(color: Colors.blue[400]), ), ); } …

Slide 50

Slide 50 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller;
 final _sizeTween = Tween(begin: 0.0, end: 300.0); final _colorTween = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]); @override initState() { super.initState(); controller = AnimationController( .. controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(controller), height: _sizeTween.evaluate(controller), decoration: BoxDecoration(color: Colors.blue[400]), // decoration: BoxDecoration(color: Colors.blue[400]), ), ); } … beginʹ੨ɺendʹԫ৭Λ౉ͯ͠ ColorTween ΠϯελϯεΛੜ੒ɻ

Slide 51

Slide 51 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller;
 final _sizeTween = Tween(begin: 0.0, end: 300.0); final _colorTween = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]); @override initState() { super.initState(); controller = AnimationController( .. controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(controller), height: _sizeTween.evaluate(controller), decoration: BoxDecoration(color: _colorTween.evaluate(controller)), // decoration: BoxDecoration(color: Colors.blue[400]), ), ); } … buildϝιουͷதͰɺ ColorTween ͔Β Color ΛऔΓग़ͯ͠ηοτɻ

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

CurvedAnimation Ͱ؇ٸΛ͚ͭΔ

Slide 54

Slide 54 text

CurvedAnimation - Ξχϝʔγϣϯͷ஋ͷมԽʹ؇ٸΛ͚ͭΔ

Slide 55

Slide 55 text

Curves.ease

Slide 56

Slide 56 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; Animation animation; .. @override initState() { super.initState(); controller = AnimationController( .. animation = CurvedAnimation(parent: controller, curve: Curves.ease); controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(animation), height: _sizeTween.evaluate(animation), decoration: BoxDecoration(color: _colorTween.evaluate(animation)), ), ); } ..

Slide 57

Slide 57 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; Animation animation; .. @override initState() { super.initState(); controller = AnimationController( .. animation = CurvedAnimation(parent: controller, curve: Curves.ease); controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(animation), height: _sizeTween.evaluate(animation), decoration: BoxDecoration(color: _colorTween.evaluate(animation)), ), ); } .. initState()ͷதͰɺCurvedAnimationΛੜ੒ɻ ୈೋҾ਺ͰCurveΛࢦఆ͢Δɻ

Slide 58

Slide 58 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; Animation animation; .. @override initState() { super.initState(); controller = AnimationController( .. animation = CurvedAnimation(parent: controller, curve: Curves.ease); controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(animation), height: _sizeTween.evaluate(animation), decoration: BoxDecoration(color: _colorTween.evaluate(animation)), ), ); } .. buildϝιουͷதͰTween͔Β஋ΛऔΓग़͢ࡍʹ controllerͷ୅ΘΓʹanimationΛࢦఆ͢Δɻ

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

Curves - bounceIn/bounceInOut/bounceOut - Decelerate - ease/easeIn/easeInOut/easeOut - elasticIn/elasticInOut/elasticOut - FastOutSlowIn - Linear - https://docs.flutter.io/flutter/animation/Curves-class.html

Slide 61

Slide 61 text

Animation෦෼Λ Widgetʹ੾Γग़͢

Slide 62

Slide 62 text

͜͜·Ͱͷ໰୊఺ - Animationͷίʔυ͕ࢄΒ͹͍ͬͯΔ - Animation͢ΔWidget͕૿͑ͨΓෳࡶʹ ͳͬͨͱ͖ʹେม

Slide 63

Slide 63 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; Animation animation; final _sizeTween = Tween(begin: 0.0, end: 300.0); final _colorTween = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]); .. @override initState() { super.initState(); controller = AnimationController( .. animation = CurvedAnimation(parent: controller, curve: Curves.ease); controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(animation), height: _sizeTween.evaluate(animation), decoration: BoxDecoration(color: _colorTween.evaluate(animation)), ), ); } ..

Slide 64

Slide 64 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { AnimationController controller; Animation animation; final _sizeTween = Tween(begin: 0.0, end: 300.0); final _colorTween = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]); .. @override initState() { super.initState(); controller = AnimationController( .. animation = CurvedAnimation(parent: controller, curve: Curves.ease); controller.forward(); } @override Widget build(BuildContext context) { return Center( child: Container( width: _sizeTween.evaluate(animation), height: _sizeTween.evaluate(animation), decoration: BoxDecoration(color: _colorTween.evaluate(animation)), ), ); } .. ͜ͷ͋ͨΓΛ1ͭͷWidgetʹ·ͱΊΕ͹ ݟ௨͠΋Α͘ͳΔ͠࠶ར༻΋ՄೳʹͳΔɻ

Slide 65

Slide 65 text

Animation͢Δ෦෼Λ Widgetͱͯ͠੾Γग़͠

Slide 66

Slide 66 text

class SampleAnimation extends StatelessWidget { SampleAnimation({Key key, this.controller}) : sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation(parent: controller, curve: Curves.ease), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]).animate( CurvedAnimation(parent: controller, curve: Curves.ease), ), super(key: key); final Animation controller; final Animation sizeAnimation; final Animation colorAnimation; @override Widget build(BuildContext context) { return Center( child: Container( width: sizeAnimation.value, height: sizeAnimation.value, decoration: BoxDecoration(color: colorAnimation.value), ), ); } }

Slide 67

Slide 67 text

class SampleAnimation extends StatelessWidget { SampleAnimation({Key key, this.controller}) : sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation(parent: controller, curve: Curves.ease), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]).animate( CurvedAnimation(parent: controller, curve: Curves.ease), ), super(key: key); final Animation controller; final Animation sizeAnimation; final Animation colorAnimation; @override Widget build(BuildContext context) { return Center( child: Container( width: sizeAnimation.value, height: sizeAnimation.value, decoration: BoxDecoration(color: colorAnimation.value), ), ); } } Ҿ਺ʹAnimationControllerΛ࣋ͭ StatelessWidgetɻ

Slide 68

Slide 68 text

class SampleAnimation extends StatelessWidget { SampleAnimation({Key key, this.controller}) : sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation(parent: controller, curve: Curves.ease), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]).animate( CurvedAnimation(parent: controller, curve: Curves.ease), ), super(key: key); final Animation controller; final Animation sizeAnimation; final Animation colorAnimation; @override Widget build(BuildContext context) { return Center( child: Container( width: sizeAnimation.value, height: sizeAnimation.value, decoration: BoxDecoration(color: colorAnimation.value), ), ); } } TweenͱCurvedAnimationΛ࢖ͬͯ sizeAnimationͱcolorAnimationΛ ίϯετϥΫλͰੜ੒͓ͯ͘͠ɻ

Slide 69

Slide 69 text

class SampleAnimation extends StatelessWidget { SampleAnimation({Key key, this.controller}) : sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation(parent: controller, curve: Curves.ease), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]).animate( CurvedAnimation(parent: controller, curve: Curves.ease), ), super(key: key); final Animation controller; final Animation sizeAnimation; final Animation colorAnimation; @override Widget build(BuildContext context) { return Center( child: Container( width: sizeAnimation.value, height: sizeAnimation.value, decoration: BoxDecoration(color: colorAnimation.value), ), ); } } buildϝιουͷதͰ sizeAnimationͱColorAnimationͷ ஋Λ࢖ͬͯWidgetπϦʔΛߏஙɻ

Slide 70

Slide 70 text

AnimationController controller; // Animation animation; // final _sizeTween = Tween(begin: 0.0, end: 300.0); // final _colorTween = // ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]); @override initState() { super.initState(); controller = AnimationController( .. // animation = CurvedAnimation(parent: controller, curve: Curves.ease); // _sizeTween.animate(animation); // _colorTween.animate(animation); controller.forward(); } @override Widget build(BuildContext context) { // timeDilation = 2.0; // return Center( // child: Container( // width: _sizeTween.evaluate(animation), // height: _sizeTween.evaluate(animation), // decoration: BoxDecoration(color: _colorTween.evaluate(animation)), // ), // ); return SampleAnimation(controller: controller); } ݺͼग़͠ଆ͸controller੍͚ͩޚ͢Ε͹Α͍ɻ

Slide 71

Slide 71 text

AnimatedBuilder ͰϦϑΝΫλϦϯά

Slide 72

Slide 72 text

͜͜·Ͱͷ໰୊఺ setState()ΛݺͿͨΊ͚ͩʹListenerΛ ηοτ͍ͯ͠Δ৑௕ͳίʔυ͕͋Δɻ

Slide 73

Slide 73 text

@override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) ..addListener(() { setState(() {}); }) ..addStatusListener((status) { if (status == AnimationStatus.completed) { controller.reverse(); } else if (status == AnimationStatus.dismissed) { controller.forward(); } }); controller.forward(); }

Slide 74

Slide 74 text

@override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) ..addListener(() { setState(() {}); }) ..addStatusListener((status) { if (status == AnimationStatus.completed) { controller.reverse(); } else if (status == AnimationStatus.dismissed) { controller.forward(); } }); controller.forward(); } ࠶ඳը͢ΔͨΊʹListenerΛηοτͯ͠ setState()ΛݺͿ৑௕ͳίʔυɻ => AnimatedBuilderΛ࢖ͬͯলུՄೳɻ

Slide 75

Slide 75 text

AnimatedBuilder - controllerͷมߋΛݕ஌ͯ͠࠶ඳը͠௚͢ AnimatedWidgetΛܧঝ͍ͯ͠Δ - builderͱcontrollerΛҾ਺ʹ౉ͯ͠ WidgetΛ૊ΈཱͯΔ

Slide 76

Slide 76 text

class SampleAnimation extends StatelessWidget { .. Widget _buildAnimation(BuildContext context, Widget child) { return Center( child: Container( width: sizeAnimation.value, height: sizeAnimation.value, decoration: BoxDecoration(color: colorAnimation.value), ), ); } @override Widget build(BuildContext context) { return AnimatedBuilder( builder: _buildAnimation, animation: controller, ); } }

Slide 77

Slide 77 text

class SampleAnimation extends StatelessWidget { .. Widget _buildAnimation(BuildContext context, Widget child) { return Center( child: Container( width: sizeAnimation.value, height: sizeAnimation.value, decoration: BoxDecoration(color: colorAnimation.value), ), ); } @override Widget build(BuildContext context) { return AnimatedBuilder( builder: _buildAnimation, animation: controller, ); } } buildϝιουͷதͰ AnimatedBuilderΛฦ͢ɻ

Slide 78

Slide 78 text

class SampleAnimation extends StatelessWidget { .. Widget _buildAnimation(BuildContext context, Widget child) { return Center( child: Container( width: sizeAnimation.value, height: sizeAnimation.value, decoration: BoxDecoration(color: colorAnimation.value), ), ); } @override Widget build(BuildContext context) { return AnimatedBuilder( builder: _buildAnimation, animation: controller, ); } } builderʹ͸WidgetΛੜ੒͢Δؔ਺Λ౉͢ɻ

Slide 79

Slide 79 text

class _BasicAnimationAppState extends State with SingleTickerProviderStateMixin { .. @override initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this) // ..addListener(() { // setState(() {}); // }) .. } ݺͼग़͠ݩͰ͸ addListenerͱsetState͕ෆཁʹɻ

Slide 80

Slide 80 text

AnimatedWidget ͱ AnimatedBuilder ͷ࢖͍෼͚ /// A general-purpose widget for building animations. /// /// AnimatedBuilder is useful for more complex widgets that wish to include /// an animation as part of a larger build function. To use AnimatedBuilder, /// simply construct the widget and pass it a builder function. /// /// For simple cases without additional state, consider using /// [AnimatedWidget]. /// /// ## Performance optimizations /// /// If your [builder] function contains a subtree that does not depend on the /// animation, it's more efficient to build that subtree once instead of /// rebuilding it on every animation tick. /// /// If you pass the pre-built subtree as the [child] parameter, the /// AnimatedBuilder will pass it back to your builder function so that you /// can incorporate it into your build. /// /// Using this pre-built child is entirely optional, but can improve /// performance significantly in some cases and is therefore a good practice.

Slide 81

Slide 81 text

AnimatedWidget ͱ AnimatedBuilder ͷ࢖͍෼͚ /// A general-purpose widget for building animations. /// /// AnimatedBuilder is useful for more complex widgets that wish to include /// an animation as part of a larger build function. To use AnimatedBuilder, /// simply construct the widget and pass it a builder function. /// /// For simple cases without additional state, consider using /// [AnimatedWidget]. /// /// ## Performance optimizations /// /// If your [builder] function contains a subtree that does not depend on the /// animation, it's more efficient to build that subtree once instead of /// rebuilding it on every animation tick. /// /// If you pass the pre-built subtree as the [child] parameter, the /// AnimatedBuilder will pass it back to your builder function so that you /// can incorporate it into your build. /// /// Using this pre-built child is entirely optional, but can improve /// performance significantly in some cases and is therefore a good practice. builderͷඞཁͷͳ͍γϯϓϧͳWidgetͷ ৔߹ʹ͸ɺAnimatedWidgetΛ࢖͏ͷ͕Α͍ɻ Ξχϝʔγϣϯ͠ͳ͍WidgetΛؚΉ৔߹ʹ͸ɺ AnimatedBuilderΛ࢖͏ํ͕ແବͳ࠶ඳըΛ͠ ͳ͍ͷͰύϑΥʔϚϯε͕Α͍ɻ

Slide 82

Slide 82 text

AnimatedWidget - RelativePositionedTransition - SlideTransition - SizeTransition - ScaleTransition - DecoratedBoxTransition - RotationTransition - PositionedTransition - AlignTransition

Slide 83

Slide 83 text

AnimatedBuilder - BottomSheet - ExpansionTile - PopupMenu - ProgressIndicator - RefreshIndicator - Scaffold - SnackBar - TabBar - TextField

Slide 84

Slide 84 text

࿈ଓͨ͠ ΞχϝʔγϣϯΛ࡞Δ

Slide 85

Slide 85 text

ॱ൪ʹΞχϝʔγϣϯ ੨͔ΒԫʹมԽ͠ͳ͕Β େ͖͞΋มԽ͢Δ " େ͖͕͞มԽ͔ͯ͠Β ੨͔ΒԫʹมԽ͢Δ

Slide 86

Slide 86 text

IntervalΛ࢖͏ - CurveΛܧঝͨ͠Ϋϥε - 0.0 ~ 1.0ͷؒͰΞχϝʔγϣϯͷ։࢝ͱऴ ྃλΠϛϯάΛࢦఆ͢Δ

Slide 87

Slide 87 text

class SampleAnimation extends StatelessWidget { SampleAnimation({Key key, this.controller}) : sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation( parent: controller, curve: Interval(0.0, 0.5, curve: Curves.ease), // curve: Curves.ease, ), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]) .animate( CurvedAnimation( parent: controller, curve: Interval(0.5, 0.9, curve: Curves.ease), // curve: Curves.ease, ), ), super(key: key);

Slide 88

Slide 88 text

class SampleAnimation extends StatelessWidget { SampleAnimation({Key key, this.controller}) : sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation( parent: controller, curve: Interval(0.0, 0.5, curve: Curves.ease), // curve: Curves.ease, ), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]) .animate( CurvedAnimation( parent: controller, curve: Interval(0.5, 0.9, curve: Curves.ease), // curve: Curves.ease, ), ), super(key: key); 0 ~ 1000msͷؒͰΞχϝʔγϣϯ 1000 ~ 1800msͷؒͰΞχϝʔγϣϯ

Slide 89

Slide 89 text

No content

Slide 90

Slide 90 text

ಉ͡΍ΓํͰ૊Έ߹ΘͤΒΕΔ TJ[F d DPMPS d SPUBUF d SBEJVT d OPOF d

Slide 91

Slide 91 text

sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation( parent: controller, curve: Interval(0.0, 0.3, curve: Curves.ease), ), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]) .animate( CurvedAnimation( parent: controller, curve: Interval(0.3, 0.7, curve: Curves.ease), ), ), rotateAnimation = Tween(begin: 0.0, end: 0.75).animate( CurvedAnimation( parent: controller, curve: Interval(0.4, 0.7, curve: Curves.ease), ), ), borderRadiusAnimation = BorderRadiusTween( begin: BorderRadius.circular(0.0), end: BorderRadius.circular(150.0), ).animate( CurvedAnimation( parent: controller, curve: Interval(0.7, 0.9, curve: Curves.ease), ), ),

Slide 92

Slide 92 text

sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation( parent: controller, curve: Interval(0.0, 0.3, curve: Curves.ease), ), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]) .animate( CurvedAnimation( parent: controller, curve: Interval(0.3, 0.7, curve: Curves.ease), ), ), rotateAnimation = Tween(begin: 0.0, end: 0.75).animate( CurvedAnimation( parent: controller, curve: Interval(0.4, 0.7, curve: Curves.ease), ), ), borderRadiusAnimation = BorderRadiusTween( begin: BorderRadius.circular(0.0), end: BorderRadius.circular(150.0), ).animate( CurvedAnimation( parent: controller, curve: Interval(0.7, 0.9, curve: Curves.ease), ), ), sizeAnimation : 0 ~ 0.6ඵͰେ͖͘ͳΔɻ

Slide 93

Slide 93 text

sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation( parent: controller, curve: Interval(0.0, 0.3, curve: Curves.ease), ), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]) .animate( CurvedAnimation( parent: controller, curve: Interval(0.3, 0.7, curve: Curves.ease), ), ), rotateAnimation = Tween(begin: 0.0, end: 0.75).animate( CurvedAnimation( parent: controller, curve: Interval(0.4, 0.7, curve: Curves.ease), ), ), borderRadiusAnimation = BorderRadiusTween( begin: BorderRadius.circular(0.0), end: BorderRadius.circular(150.0), ).animate( CurvedAnimation( parent: controller, curve: Interval(0.7, 0.9, curve: Curves.ease), ), ), colorAnimation : 0.6 ~ 1.4ඵͰ৭Λม͑Δɻ rotateAnimation : 0.8 ~ 1.4ඵͰ270౓ճస͢Δɻ

Slide 94

Slide 94 text

sizeAnimation = Tween(begin: 0.0, end: 300.0).animate( CurvedAnimation( parent: controller, curve: Interval(0.0, 0.3, curve: Curves.ease), ), ), colorAnimation = ColorTween(begin: Colors.blue[400], end: Colors.yellow[400]) .animate( CurvedAnimation( parent: controller, curve: Interval(0.3, 0.7, curve: Curves.ease), ), ), rotateAnimation = Tween(begin: 0.0, end: 0.75).animate( CurvedAnimation( parent: controller, curve: Interval(0.4, 0.7, curve: Curves.ease), ), ), borderRadiusAnimation = BorderRadiusTween( begin: BorderRadius.circular(0.0), end: BorderRadius.circular(150.0), ).animate( CurvedAnimation( parent: controller, curve: Interval(0.7, 0.9, curve: Curves.ease), ), ), borderRadiusAnimation : 1.4 ~ 1.8ඵͰ˘Λ˓ʹมԽͤ͞Δɻ

Slide 95

Slide 95 text

Widget _buildAnimation(BuildContext context, Widget child) { return Center( child: Transform( transform: Matrix4.rotationZ(rotateAnimation.value * math.pi * 2.0), alignment: Alignment.center, child: Container( width: sizeAnimation.value, height: sizeAnimation.value, decoration: BoxDecoration( color: colorAnimation.value, borderRadius: borderRadiusAnimation.value), ), ), ); } ֤animationͷ஋Λ࢖ͬͯWidgetπϦʔΛߏஙɻ

Slide 96

Slide 96 text

No content

Slide 97

Slide 97 text

·ͱΊ

Slide 98

Slide 98 text

AnimationController Ξχϝʔγϣϯͷ࣌ؒ΍ ։࢝ɾऴྃͳͲΛ੍ޚ͢Δɻ

Slide 99

Slide 99 text

Tween ΞχϝʔγϣϯͰมߋ͢Δ ஋(0.0 ~ 0.1)Λɺผͷ਺ ࣈ΍৭ͳͲͷ஋ʹม׵͢Δɻ

Slide 100

Slide 100 text

CurvedAnimation ΞχϝʔγϣϯͰมԽ͢Δ ஋ͷ؇ٸΛ͚ͭΔɻ IntervalΛ࢖͑͹࣮ߦλΠ ϛϯά΋ม͑ΒΕΔɻ

Slide 101

Slide 101 text

AnimatedBuilder AnimationControllerͷ ஋͕มߋ͞ΕΔ͝ͱʹ ඳը͢ΔWidgetΛͭ͘ΔϏ ϧμʔɻ

Slide 102

Slide 102 text

΋ͬͱ஌Γ͍ͨํ͸ͪ͜Β - FlutterΞχϝʔγϣϯͷΫϥε΍֓೦ɺͦΕΒΛ૊Έ߹Θͤͨ αϯϓϧͷઆ໌
 https://flutter.io/tutorials/animation/
 https://flutter.io/animations/ - TweenͷΧελϚΠζ΍AnimatedBuilderͷೖΕࢠͳͲɺগ͠ ෳࡶͳάϥϑΞχϝʔγϣϯΛ࡞ΔνϡʔτϦΞϧ
 https://medium.com/flutter-io/zero-to-one-with-flutter-43b13fd7b354
 https://medium.com/flutter-io/zero-to-one-with-flutter-part-two- 5aa2f06655cb

Slide 103

Slide 103 text

Thanks! Enjoy Flutter!