I am trying to build a widget that can be shown or hidden, and when it is shown, will have is displayed text 'grow' over a certain duration. I've based it mostly on the typing indicator example.
The idea is to have the widget in e.g. a form with state and provide some pretty user feedback in certain circumstances, such as during and after a validation REST call.
I can't quite figure out how to 'plug in' the AnimationController, in order to grow substring of the input string to display.
i.e. in the form the widget will be something like
AnimatedText(
textContent: stringFeedback,
doShowMe: haveFeedback,
),
... and in my async input processing method i have a setState(() => haveFeedback = true);
and a false etc.
I imagine I need to call a something like the updateText() method below from somewhere somehow linked the the value of the AnimationControler _appearanceController
but how to have that be a loop escapes me - still being new to the flutter/Dart and for that matter OOP paradigm.
What I have so far is:
import 'package:flutter/material.dart';
import 'dart:developer' as developer;
class AnimatedText extends StatefulWidget {
const AnimatedText({
Key? key,
this.doShowMe = false,
this.textContent = '',
}) : super(key: key);
final bool doShowMe;
final String textContent;
@override
State<AnimatedText> createState() => _AnimatedTextState();
}
class _AnimatedTextState extends State<AnimatedText>
with SingleTickerProviderStateMixin {
late AnimationController _appearanceController;
late String displayText;
@override
void initState() {
super.initState();
developer.log('_AnimatedTextState init ');
_appearanceController = AnimationController(vsync: this);
displayText = '';
if (widget.doShowMe) {
_doShowMe();
}
}
@override
void didUpdateWidget(AnimatedText oldWidget) {
super.didUpdateWidget(oldWidget);
developer.log('_AnimatedTextState didUpdateWidget');
if (widget.doShowMe != oldWidget.doShowMe) {
if (widget.doShowMe) {
developer.log('_AnimatedTextState didUpdateWidget show');
_doShowMe();
} else {
developer.log('_AnimatedTextState didUpdateWidget hide');
_hideIndicator();
}
}
}
@override
void dispose() {
developer.log('_AnimatedTextState dispose');
_appearanceController.dispose();
displayText = '';
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _appearanceController,
builder: (context, child) {
return Container(
child: Text(displayText),
);
});
}
void updateText() {
//something like...
String payload = widget.textContent;
if (displayText != payload) {
int numCharsToShow =
(_appearanceController.value * widget.textContent.length).ceil();
displayText = payload.substring(0, numCharsToShow);
developer.log('updated displayText up to $numCharsToShow');
}
}
void _doShowMe() {
_appearanceController
..duration = const Duration(milliseconds: 750)
..forward();
}
void _hideIndicator() {
_appearanceController
..duration = const Duration(milliseconds: 150)
..reverse();
}
}
Any help much appreciated.