-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Closed
Labels
P3Issues that are less important to the Flutter projectIssues that are less important to the Flutter projecta: animationAnimation APIsAnimation APIsc: proposalA detailed proposal for a change to FlutterA detailed proposal for a change to Flutterframeworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.r: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Description
Use case
I am using an implicit Animation widget and an explicit animating widget, and I would like to be able to add a listener to see when the implicit widget is done to then call my explicitly animated widget. In short, I would like the AnimatedSize to finish animating before changing the Opacity. And, not stopping there, I would like to be able to chain the animations for all implicitly animated widgets. Something along the lines of
AnimatedSize(
onFinishAnimating: () {
driveExplicitAnimation();
// or
setState(() {
setAnotherAnimatedWidgetsValue();
});
}
child: Container()
);
Proposal
add callback/listener on implicitly animated widget to call explicitly animated widget when the implicitly animated widget is done animating.
Sample Code
Note: While the sample code does not have any explicitly animated widgets, it provides the two types of "desired" animations from the implicitly animated widgets. But, because there is nothing that allows me to snoop on their animations (diving into the code for Animated Size, it seems that the animation controller is private, not allowing me to user key.currentState.findRenderObject), thus is not allowing me to better chain animations. When I set the child of the expanded content, I would like the AnimatedSize to finish animating before changing the Opacity.
Details
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<int> rows = List.filled(5, 0);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView.builder(itemBuilder: ((context, index) {
return AnimatingRow(rowNum: index, info: "Info at a glance");
})));
}
}
class AnimatingRow extends StatefulWidget {
final int rowNum;
final String info;
const AnimatingRow({super.key, required this.rowNum, required this.info});
@override
AnimatingRowState createState() => AnimatingRowState();
}
class AnimatingRowState extends State<AnimatingRow> {
static const String _showMoreText = "Show More";
static const String _showLessText = "Show Less";
static const rowColor = Color.fromARGB(255, 235, 235, 235);
static const fillerText =
"asdfjaslkdfjlsdjkfalskdjfalasodifj;lasdfjlkasjfd;lkajsdfljkas;dflkjas;dlkfja;sldjfasldkjflasdjf;lsakjdfl;asjdflsdkjfal;sdjf;alsdjfk;lasdjf;lasjdf;lasjdfl;askjdfl;ajsdfjkasdf";
late bool showingMore;
late double childOpacity;
late final int rowNum;
late String _showText;
Widget moreWidget = Container();
@override
void initState() {
_showText = _showMoreText;
showingMore = false;
childOpacity = 0;
rowNum = widget.rowNum;
super.initState();
}
Color? getRowColor(int rowNumber) {
if (rowNumber.isEven) {
return rowColor;
} else {
return null;
}
}
void showButtonPress() {
if (showingMore) {
setState(() {
_showText = _showMoreText;
showingMore = false;
moreWidget = Container();
childOpacity = 0;
});
} else {
const exampleList = Text(fillerText);
setState(() {
_showText = _showLessText;
showingMore = true;
moreWidget = exampleList;
childOpacity = 1;
});
}
}
@override
Widget build(BuildContext context) {
return AnimatedSize(
duration: const Duration(milliseconds: 250),
child: ColorBackground(
backgroundColor: getRowColor(rowNum),
margin: const EdgeInsets.only(
left: 20,
right: 20,
),
child: Column(children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
textDirection: TextDirection.ltr,
children: [
Text(widget.info),
Align(
alignment: Alignment.bottomRight,
child: TextButton(
onPressed: showButtonPress,
child: Text(_showText),
))
],
),
AnimatedOpacity(
duration: const Duration(milliseconds: 250),
opacity: childOpacity,
child: moreWidget,
)
])));
}
}
class ColorBackground extends Container {
final double radius;
final double opacity;
final MainAxisAlignment mainAxisAlignment;
late final Color? backgroundColor;
ColorBackground(
{super.key,
super.child,
this.opacity = 1,
super.width,
super.height,
super.constraints,
this.backgroundColor = Colors.grey,
this.radius = 10,
this.mainAxisAlignment = MainAxisAlignment.center,
super.padding = const EdgeInsets.all(15),
super.margin});
@override
BoxDecoration get decoration {
return BoxDecoration(
color: backgroundColor?.withOpacity(opacity),
borderRadius: BorderRadius.all(Radius.circular(radius)));
}
}
Metadata
Metadata
Assignees
Labels
P3Issues that are less important to the Flutter projectIssues that are less important to the Flutter projecta: animationAnimation APIsAnimation APIsc: proposalA detailed proposal for a change to FlutterA detailed proposal for a change to Flutterframeworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.r: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team