在选定的 TextButton 之间设置动画

Animate between a selected TextButton

我正在为 select 需要的年份和月份构建一个面板。作为背景,我创建了一个三元组,它检查当前按钮 == 是否处于月份状态。但是一个月的变化(因此 backgroundColor 变化)没有动画。添加它的简单方法是什么?透明和强调色之间的不透明度过渡之类的东西。谢谢。

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(),
            ],
          ),
        ),
      ),
    );
  }
}

您可以使用AnimatedSwitcher制作转场动画。如果您想获得有关小部件的更多信息,请参阅 AnimatedSwitcher: widget of the week

这是 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;
}