I am building a panel to select needed year & month. As a background I created a ternary which checks if the current button == the month in state. But the change of a month (therefore a backgroundColor change) has no animation. What would be the simple ways to add it? Something like opacity transition between transparent and the accent color. Thank you.

enter image description here

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class Time extends StatefulWidget {
  @override
  _TimeState createState() => _TimeState();
}

class _TimeState extends State<Time> {
  int _selectedMonth = DateTime.now().month;

  List<Widget> generateMonths() {
    List<Widget> generateRowOfMonths(from, to) {
      List<Widget> months = [];
      for (int i = from; i <= to; i++) {
        months.add(
          TextButton(
            onPressed: () {
              setState(() {
                _selectedMonth = i;
              });
            },
            style: TextButton.styleFrom(
              backgroundColor: _selectedMonth == i
                  ? Theme.of(context).accentColor
                  : Colors.transparent,
              shape: CircleBorder(),
            ),
            child: Text(
              DateFormat('MMM').format(
                DateTime(2021, i, 1),
              ),
            ),
          ),
        );
      }
      return months;
    }

    return [
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: generateRowOfMonths(1, 6),
      ),
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: generateRowOfMonths(7, 12),
      ),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Material(
        color: Theme.of(context).cardColor,
        child: Container(
          child: Column(
            children: [
              Row(
                children: [
                  IconButton(
                    onPressed: () {},
                    icon: Icon(Icons.navigate_before_rounded),
                  ),
                  Expanded(
                    child: Center(
                      child: Text(
                        '2020',
                        style: TextStyle(fontWeight: FontWeight.bold),
                      ),
                    ),
                  ),
                  IconButton(
                    onPressed: () {},
                    icon: Icon(Icons.navigate_next_rounded),
                  ),
                ],
              ),
              ...generateMonths(),
            ],
          ),
        ),
      ),
    );
  }
}


Solution 1: MaNDOOoo

You can make the transition animation by using AnimatedSwitcher. If you want to get more info about the widget, see AnimatedSwitcher: widget of the week.

Here is a complete function that is inner of generateMonths().

List<Widget> generateRowOfMonths(from, to) {
  List<Widget> months = [];
  for (int i = from; i <= to; i++) {
    final backgroundColor = _selectedMonth == i
        ? Theme.of(context).accentColor
        : Colors.transparent;
    months.add(
      AnimatedSwitcher(
        duration: kThemeChangeDuration,
        transitionBuilder: (Widget child, Animation<double> animation) {
          return FadeTransition(
            child: child,
            opacity: animation,
          );
        },
        child: TextButton(
          key: ValueKey(backgroundColor),
          onPressed: () {
            setState(() {
              _selectedMonth = i;
            });
          },
          style: TextButton.styleFrom(
            backgroundColor: backgroundColor,
            shape: CircleBorder(),
          ),
          child: Text(
            DateFormat('MMM').format(
              DateTime(2021, i, 1),
            ),
          ),
        ),
      ),
    );
  }
  return months;
}