FlareActor callback never called
workerbee22 opened this issue · 3 comments
Continuing to try and get a basic countdown going. Sample code uses the flare speed control example https://github.com/luigi-rosso/flare_control_speed_example/blob/master/lib/main.dart
Using flare_flutter 1.7.3
This code never prints"finished":
import 'package:flutter/material.dart';
import 'dart:async'; // for Timer
import 'package:flutter/material.dart';
import 'package:flare_flutter/flare.dart';
import 'package:flare_flutter/flare_actor.dart';
import 'package:flare_flutter/flare_controller.dart';
import 'package:flare_dart/math/mat2d.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flare Single Digit',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flare Single Digit'),
);
}
}
/// Flare related -----------------------------------------------------------------------------------------
/// From Flare contact, see issue https://github.com/2d-inc/Flare-Flutter/issues/167
/// Sample code here: https://github.com/luigi-rosso/flare_control_speed_example/blob/master/lib/main.dart
class SpeedController extends FlareController {
final String animationName;
ActorAnimation _animation;
double speed;
double _time = 0;
// Optional param spped defaults to 1 if not provided
SpeedController(this.animationName, {this.speed = 1});
@override
bool advance(FlutterActorArtboard artboard, double elapsed) {
if (_animation == null) {
return false;
}
if (_animation.isLooping) {
_time %= _animation.duration;
}
_animation.apply(_time, artboard, 1.0);
_time += elapsed * speed;
// Stop advancing if animation is done and we're not looping.
return _animation.isLooping || _time < _animation.duration;
}
@override
void initialize(FlutterActorArtboard artboard) {
_animation = artboard.getAnimation(animationName);
}
@override
void setViewTransform(Mat2D viewTransform) {
// intentionally empty, we don't need the viewTransform in this controller
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int digit = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 150,
width: 80,
/// FlareActor()
// Use controller to specify which animation and see above controls speed and thus duration
// but the artboard ie. the digit is passed in here
child: Digit(digit),
),
RaisedButton(
child: Text(
"Next",
),
elevation: 2.0,
onPressed: () {
setState(() {
if(digit == 9) {
digit = 0;
} else {
digit = digit + 1;
}
});
},
),
],
),
),
);
}
}
// Digit - single digit using the flare SpeedController
class Digit extends StatefulWidget {
final int digitNew;
Digit(this.digitNew);
@override
_DigitState createState() => _DigitState();
}
class _DigitState extends State<Digit> {
SpeedController controller;
@override
void initState() {
super.initState();
// Instantiate a speed controlled controller for the animation
controller = SpeedController("in", speed: 0.1);
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(0.0),
padding: const EdgeInsets.all(0.0),
child: Stack(
children: <Widget>[
SizedBox(
height: 150,
width: 80,
/// FlareActor()
// Use controller to specify which animation and see above controls speed and thus duration
// but the artboard ie. the digit is passed in here
child: FlareActor(
"assets/io_2018_digits.flr",
controller: controller,
artboard: widget.digitNew.toString(),
fit: BoxFit.contain,
callback: (value) {
print('finished?');
},
),
),
]
),
);
}
}
The callback registered within FlareActor
is used on the animations that are played through FlareActor
only.
Since you're playing animations with your SpeedController
, you should add a callback parameter to that as well:
class SpeedController extends FlareController {
[...]
FlareCompletedCallback onAnimationCompleted;
// Optional param spped defaults to 1 if not provided
SpeedController(this.animationName, {this.speed = 1, this.onAnimationCompleted});
@override
bool advance(FlutterActorArtboard artboard, double elapsed) {
if (_animation == null) {
return false;
}
if (_animation.isLooping) {
_time %= _animation.duration;
}
_animation.apply(_time, artboard, 1.0);
_time += elapsed * speed;
if (_time > _animation.duration && onAnimationCompleted != null) {
onAnimationCompleted(_animation.name);
}
// Stop advancing if animation is done and we're not looping.
return _animation.isLooping || _time < _animation.duration;
}
[...]
}
Thanks @umberto-sonnino but is there any documentation on how FlareCompletedCallback works? Changes above crash when onAnimationCompleted(_animation.name);
is executed.
FlareCompletedCallback
is just a type definition:
typedef void FlareCompletedCallback(String name);
It is a function that takes a String parameter and doesn't return any value.
In the snippet above, you need to specify a callback in the constructor for it to not crash. I'll update it with a null check!
And when instantiating your SpeedController
:
SpeedController(
myAnimationName,
onAnimationCompleted: (name) {
print("Animation $name completed!");
}
)