J'essaie de recréer quelque chose comme ExpansionTile
mais dans un Card
. Lorsque je clique sur la carte, son enfant s'affiche et la carte change de hauteur, je souhaite donc animer ce changement.
J'ai essayé d'utiliser AnimatedContainer
et GlobalKey
pour connaître la taille finale de la carte avec son enfant rendu, puis j'ai défini la nouvelle hauteur sur AnimatedContainer
mais cela n'a pas fonctionné.
Au final, je n'ai eu qu'à utiliser AnimatedSize
. Il reproduit exactement l'animation que je veux.
AnimatedSize(
vsync: this,
duration: Duration(milliseconds: 150),
curve: Curves.fastOutSlowIn,
child: Container(
child: Container(
child: !_isExpanded
? null
: FadeTransition(opacity: animationFade, child: widget.child),
),
),
);
Vous pouvez utiliser le AnimatedContainer pour les animations
class Animate extends StatefulWidget {
@override
_AnimateState createState() => _AnimateState();
}
class _AnimateState extends State<Animate> {
var height = 200.0;
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return Scaffold(
body: Center(
child: AnimatedContainer(
color: Colors.amber,
duration: new Duration(milliseconds: 500),
height: height,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
if (height == 200.0) {
height = 400.0;
} else {
height = 200.0;
}
});
},
child: Icon(Icons.settings),
),
);
}
}
J'ai modifié le ExpansionTile, cela a une animation appropriée. J'espère que cela t'aides
class _FixedExpansionTileState extends State<FixedExpansionTile> with SingleTickerProviderStateMixin {
AnimationController _controller;
CurvedAnimation _easeOutAnimation;
CurvedAnimation _easeInAnimation;
ColorTween _borderColor;
ColorTween _headerColor;
ColorTween _iconColor;
ColorTween _backgroundColor;
Animation<double> _iconTurns;
bool _isExpanded = false;
@override
void initState() {
super.initState();
_controller = new AnimationController(duration: _kExpand, vsync: this);
_easeOutAnimation = new CurvedAnimation(parent: _controller, curve: Curves.easeOut);
_easeInAnimation = new CurvedAnimation(parent: _controller, curve: Curves.easeIn);
_borderColor = new ColorTween();
_headerColor = new ColorTween();
_iconColor = new ColorTween();
_iconTurns = new Tween<double>(begin: 0.0, end: 0.5).animate(_easeInAnimation);
_backgroundColor = new ColorTween();
_isExpanded = PageStorage.of(context)?.readState(context) ?? widget.initiallyExpanded;
if (_isExpanded)
_controller.value = 1.0;
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _handleTap() {
setState(() {
_isExpanded = !_isExpanded;
if (_isExpanded)
_controller.forward();
else
_controller.reverse().then<void>((value) {
setState(() {
// Rebuild without widget.children.
});
});
PageStorage.of(context)?.writeState(context, _isExpanded);
});
if (widget.onExpansionChanged != null)
widget.onExpansionChanged(_isExpanded);
}
Widget _buildChildren(BuildContext context, Widget child) {
final Color borderSideColor = Colors.transparent;
// final Color titleColor = _headerColor.evaluate(_easeInAnimation);
return new Container(
decoration: new BoxDecoration(
color: _backgroundColor.evaluate(_easeOutAnimation) ?? Colors.transparent,
border: new Border(
top: new BorderSide(color: borderSideColor),
bottom: new BorderSide(color: borderSideColor),
)
),
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconTheme.merge(
data: new IconThemeData(color: _iconColor.evaluate(_easeInAnimation)),
child: new ListTile(
onTap: _handleTap,
leading: widget.leading,
title: new DefaultTextStyle(
style: Theme.of(context).textTheme.subhead.copyWith(color: Colors.transparent),
child: widget.title,
),
trailing: widget.trailing ?? new RotationTransition(
turns: _iconTurns,
child: const Icon(Icons.expand_more),
),
),
),
new ClipRect(
child: new Align(
heightFactor: _easeInAnimation.value,
child: child,
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
_borderColor.end = theme.dividerColor;
_headerColor
..begin = theme.textTheme.subhead.color
..end = theme.accentColor;
_iconColor
..begin = theme.unselectedWidgetColor
..end = theme.accentColor;
_backgroundColor.end = widget.backgroundColor;
final bool closed = !_isExpanded && _controller.isDismissed;
return new AnimatedBuilder(
animation: _controller.view,
builder: _buildChildren,
child: closed ? null : new Column(children: widget.children),
);
}
}