2021/3/11 : Flutter : TweenAnimationBuilderについて

TweenAnimationBuilderを使ってみる。

 


とりあえず動くサンプル

import 'package:flutter/material.dart';

void main() {
  return runApp(
    MaterialApp(
      home: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:TweenAnimationBuilder(
        curve:Curves.slowMiddle, //←curveを指定できる。
        duration:Duration(seconds:4),
        tween:ColorTween(begin:Colors.white,end:Colors.pinkAccent,),
        builder:(BuildContext _,Color value,Widget child){
          return ColorFiltered(
            child:Image.asset('assets/images/diamond.png'),
            colorFilter:ColorFilter.mode(
              value,
              BlendMode.modulate,
            ),
          );
        },
      ),
    );
  }
}

 


ColorFiltered使わないパターン

import 'package:flutter/material.dart';

void main() {
  return runApp(
    MaterialApp(
      home: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: TweenAnimationBuilder(
        curve: Curves.easeIn,
        duration: Duration(seconds: 4),
        tween: ColorTween(
          begin: Colors.white,
          end: Colors.pinkAccent,
        ),
        builder: (BuildContext _, Color? value, Widget? child) {
          return Image.asset(
            'assets/images/diamond.png',
            color: value,
            colorBlendMode: BlendMode.colorBurn,
          );
        },
      ),
    );
  }
}

 

 


動画で説明されているようにonEndパラメータを設定してオレンジへの遷移が終了したらグリーンへの遷移が始まるようにする。

リビルドでオレンジ→グリーンの遷移が起こるのでStatefulWidgetにする必要がある。

import 'package:flutter/material.dart';

void main() {
  return runApp(
    MaterialApp(
      home: MyApp(),
    ),
  );
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Color _colorValue = Colors.orange;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: TweenAnimationBuilder(
          curve: Curves.easeIn,
          duration: Duration(seconds: 1),
          tween: ColorTween(
            begin: Colors.white,
            end: _colorValue,
          ),
          builder: (BuildContext _, Color? value, Widget? child) {
            return Image.asset(
              'assets/images/diamond.png',
              color: value,
              colorBlendMode: BlendMode.colorBurn,
            );
          },
          onEnd:()=>setState(
                ()=>_colorValue=Colors.green,
          ),
        ),
      ),
    );
  }
}

 

 


動画でchildプロパティを使うとパフォーマンス最適化されますよね、みたいな説明があるので、試しにbuildメソッド呼び出し回数を数えてみる。

まずchildプロパティ使わないパターン。

import 'package:flutter/material.dart';

void main() {
  return runApp(
    MaterialApp(
      home: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:TweenAnimationBuilder(
        curve:Curves.slowMiddle,
        duration:Duration(seconds:1),
        tween:ColorTween(begin:Colors.white,end:Colors.pinkAccent,),
        builder:(BuildContext _,Color? value,Widget? child){
          return ColorFiltered(
            child:DiamondImage(),
            colorFilter:ColorFilter.mode(
              value!,
              BlendMode.modulate,
            ),
          );
        },
      ),
    );
  }
}

class DiamondImage extends StatefulWidget {
  const DiamondImage({
    Key? key,
  }) : super(key: key);

  @override
  _DiamondImageState createState() => _DiamondImageState();
}

class _DiamondImageState extends State<DiamondImage> {
  int n=0;

  @override
  Widget build(BuildContext context) {
    n++;
    print("build呼び出し:$n回目");
    return Image.asset('assets/images/diamond.png');
  }
}

 

1秒間で59回buildメソッドが呼び出された。


次にchildプロパティを使うパターン。

import 'package:flutter/material.dart';

void main() {
  return runApp(
    MaterialApp(
      home: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:TweenAnimationBuilder(
        curve:Curves.slowMiddle,
        duration:Duration(seconds:1),
        tween:ColorTween(begin:Colors.white,end:Colors.pinkAccent,),
        builder:(BuildContext _,Color? value,Widget? child){
          return ColorFiltered(
            child:child,
            colorFilter:ColorFilter.mode(
              value!,
              BlendMode.modulate,
            ),
          );
        },
        child:DiamondImage(),
      ),
    );
  }
}

class DiamondImage extends StatefulWidget {
  const DiamondImage({
    Key? key,
  }) : super(key: key);

  @override
  _DiamondImageState createState() => _DiamondImageState();
}

class _DiamondImageState extends State<DiamondImage> {
  int n=0;

  @override
  Widget build(BuildContext context) {
    n++;
    print("build呼び出し:$n回目");
    return Image.asset('assets/images/diamond.png');
  }
}

 

buildメソッドの呼び出しは1回のみ。

ということで最適化されている、というお話。

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です