我正在尝试重新创建类似ExpansionTile
但在Card
. 当我单击卡片时,它的子级渲染并且卡片改变了它的高度,所以我想为这个变化设置动画。
我尝试使用AnimatedContainer
并GlobalKey
知道卡片的最终尺寸及其子渲染,然后将新高度设置为,AnimatedContainer
但这不起作用。
我正在尝试重新创建类似ExpansionTile
但在Card
. 当我单击卡片时,它的子级渲染并且卡片改变了它的高度,所以我想为这个变化设置动画。
我尝试使用AnimatedContainer
并GlobalKey
知道卡片的最终尺寸及其子渲染,然后将新高度设置为,AnimatedContainer
但这不起作用。
最后我只好使用AnimatedSize
. 它完全复制了我想要的动画。
AnimatedSize(
vsync: this,
duration: Duration(milliseconds: 150),
curve: Curves.fastOutSlowIn,
child: Container(
child: Container(
child: !_isExpanded
? null
: FadeTransition(opacity: animationFade, child: widget.child),
),
),
);
您可以将 AnimatedContainer 用于动画
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),
),
);
}
}
我调整了ExpansionTile,它有适当的动画。希望这可以帮助
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),
);
}
}