Я пишу собственную гистограмму и использую AnimatedContainer для вертикальных полос. У меня есть только один рендер, и он не анимируется. Чтобы исправить это, я установил начальную высоту на ноль для всех столбцов и принудительно перестроил. Это работает, но немного грязно. Есть ли другой способ заставить анимацию без перестройки?
Соответствующий код:
AnimatedContainer /* BAR-CHART-ITEM */ (
duration: const Duration(seconds: 1),
curve: Curves.easeOut,
width: widget.clsBarChart.dBarWidth,
height: widget.isFirst
? 0
: widget.dHeightScrollBarMax *
widget.clsBarChart.lsdHeightFactors[widget.iNdxItem],
Спасибо за ответы. Я проверю их как можно скорее и отчитаюсь.





Вы не можете использовать Animated Container напрямую для создания вертикальной панели, поскольку Animated Container не инициирует анимацию при первом рендеринге, а следует за вторым рендерингом для инициации анимации.
Вместо этого вы можете следовать приведенному ниже подходу для достижения аналогичного эффекта.
class AnimatedBar extends StatefulWidget {
final double finalHeight;
final Color color;
const AnimatedBar({Key? key, required this.finalHeight, required this.color}) : super(key: key);
@override
_AnimatedBarState createState() => _AnimatedBarState();
}
class _AnimatedBarState extends State<AnimatedBar> with TickerProviderStateMixin {
//AnimationController and Animation for animating the bar height;
AnimationController? _controller;
Animation<double>? _animation;
// flag to track if the animation has already played.
bool _hasAnimated = false;
@override
void initState() {
super.initState();
_controller = AnimationController(duration: Duration(milliseconds: 500), vsync: this);
_animation = Tween<double>(begin: 0.0, end: widget.finalHeight).animate(_controller!);
if (!_hasAnimated) {
// Trigger the animation forward only on the first render using a _hasAnimated boolean flag.
_controller!.forward();
_hasAnimated = true;
}
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation!,
builder: (context, child) => Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
height: _animation!.value,
width: 10.0, // Adjust width as needed
color: widget.color,
),
],
));
}
}
Вы можете использовать эту анимированную панель с приведенным ниже примером кода.
class Chart extends StatefulWidget {
const Chart({super.key});
@override
State<Chart> createState() => _ChartState();
}
class _ChartState extends State<Chart> {
List<double> barHeights = [50.0, 80.0, 30.0];
List<Color> barColors = [Colors.red, Colors.green, Colors.blue];
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
for (int i = 0; i < barHeights.length; i++)
AnimatedBar(finalHeight: barHeights[i], color: barColors[i]),
],
);
}
}
class ScreenDemo extends StatelessWidget {
const ScreenDemo({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(),body: Scaffold(
body: Container(
child: Chart())));
}
}
Это работает, но я буду придерживаться восстановления, потому что это очень просто.
Рассмотрев ваш вопрос, у меня возник вопрос: почему вы заставляете перестраиваться? Это связано с тем, что анимированный контейнер инициирует анимацию только при втором рендеринге, получая начальное значение анимации при первом рендеринге.