Попробуйте это решение. Я думаю, это почти то, что вам нужно. Вам просто нужно добавить виджет SizeTransition.
Спросите, если у вас есть какие-либо вопросы.
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
int _pressedButton;
Animation<double> _animation;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
);
_animation = Tween<double>(begin: 1.0, end: 0.0)
.animate(_controller)
..addListener(() {
setState(() { });
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Test"),
),
body: Column(
children: <Widget>[
Row(
children: <Widget>[
_animatedButton(1),
_animatedButton(2),
_animatedButton(3),
_animatedButton(4)
]
),
Text(_pressedButton != null ? "$_pressedButton button pressed" : "No button pressed"),
RaisedButton(
child: Text("Reset"),
onPressed: () {
_controller.reset();
}
)
]
)
);
}
Widget _animatedButton(int button) {
if (button != _pressedButton) {
return SizeTransition(
sizeFactor: _animation,
axis: Axis.horizontal,
child: Opacity(
opacity: _animation.value,
child: _button(button)
)
);
} else {
return _button(button);
}
}
Widget _button(int button) {
return RaisedButton(
onPressed: () => onButtonClick(button),
child: Text("Button $button")
);
}
void onButtonClick(int button) {
setState(() {
_pressedButton = button;
});
_controller.forward();
}
}
ОБНОВЛЕНИЕ 1
Отметьте еще один способ сделать то, что вам нужно. В приведенном ниже коде есть несколько разных вещей.
- Измените SingleTickerProviderStateMixin на TickerProviderStateMixin.
- Использование двух контроллеров анимации и анимации (для исчезновения невыбранных кнопок и перемещения левой выбранной кнопки).
- Запуск анимации последовательно (см. Анимацию для слушателей).
- Добавить bool _button, выбранный для отслеживания завершения анимации.
- Используйте _buttonSelected для создания правильного виджета (Widget _buttonsWidget ())
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
int _pressedButton = -1;
bool _buttonSelected = false;
Animation<double> _animationFadeOut;
AnimationController _controllerFadeOut;
Animation<double> _animationSlideLeft;
AnimationController _controllerSlideLeft;
@override
void initState() {
super.initState();
_initFadeOutAnimation();
_initSlideLeftAnimation();
}
void _initFadeOutAnimation() {
_controllerFadeOut = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
);
_animationFadeOut = Tween<double>(begin: 1.0, end: 0.0)
.animate(_controllerFadeOut)
..addListener(() {
setState(() {
if (_controllerFadeOut.isCompleted && !_controllerSlideLeft.isAnimating) {
_controllerSlideLeft.forward();
}
});
});
}
void _initSlideLeftAnimation() {
_controllerSlideLeft = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
);
_animationSlideLeft = Tween<double>(begin: 1.0, end: 0.0)
.animate(_controllerSlideLeft)
..addListener(() {
setState(() {
if (_controllerSlideLeft.isCompleted) {
_buttonSelected = true;
}
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Test"),
),
body: Column(
children: <Widget>[
_buttonsWidget(),
Text(_pressedButton != null ? "$_pressedButton button pressed" : "No button pressed"),
RaisedButton(
child: Text("Reset"),
onPressed: () {
_controllerFadeOut.reset();
_controllerSlideLeft.reset();
_pressedButton = -1;
_buttonSelected = false;
}
)
]
)
);
}
Widget _buttonsWidget() {
if (_buttonSelected) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[_buttonWidget(_pressedButton)]
);
} else {
return Row(
children: <Widget>[
_animatedButtonWidget(1),
_animatedButtonWidget(2),
_animatedButtonWidget(3),
_animatedButtonWidget(4)
]
);
}
}
Widget _animatedButtonWidget(int button) {
if (button == _pressedButton) {
return _buttonWidget(button);
} else {
return SizeTransition(
sizeFactor: _animationSlideLeft,
axis: Axis.horizontal,
child: Opacity(
opacity: _animationFadeOut.value,
child: _buttonWidget(button)
)
);
}
}
Widget _buttonWidget(int button) {
return RaisedButton(
onPressed: () => _onButtonClick(button),
child: Text("Button $button")
);
}
void _onButtonClick(int button) {
setState(() {
_pressedButton = button;
});
_controllerFadeOut.forward();
}
}