如何修复切换但不设置动画的AnimatedSwitcher

时间:2019-08-28 14:30:19

标签: flutter dart flutter-animation

我正在尝试在我的应用中创建新闻栏目。在此要显示新闻的页面中,我希望能够单击页面上的任意位置并获取列表中下一个新闻。到目前为止,这没有问题,但是我希望它有一个不错的动画,所以我尝试实现AnimatedSwitcher,但是我不知道为什么没有动画显示。

我尝试更改代码的层次结构。将手势检测器放在动画切换器内部,反之亦然。也可以将主容器放在其内部或外部。我尝试了一个动画生成器,可以缩放它以防万一它不够明显但什么也没有。也尝试过更改持续时间,不是吗。

class ShowNews extends StatefulWidget {
  @override
  _ShowNewsState createState() => _ShowNewsState();
}

class _ShowNewsState extends State<ShowNews> {
  List<News> _news = [
    News(title: 'OYÉ OYÉ', desc: 'bla bla bla bla bla'),
    News(title: 'another one', desc: 'plus de bout d\'histoire'),
    News(title: 'boum', desc: 'attention à l\'accident'),
    News(title: 'Lorem ipsum', desc: 'Lorem ipsum in doloris'),
  ];

  int _currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        setState(() {
          if (_currentIndex < _news.length - 1) {
            _currentIndex++;
          } else {
            _currentIndex = 0;
          }
        });
      },
      child: Container(
        height: 160,
        padding: EdgeInsets.all(20.0),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(20.0),
            topRight: Radius.circular(20.0),
          ),
        ),
        child: AnimatedSwitcher(
          duration: Duration(seconds: 5),
          child: ColumnArticle(_news, _currentIndex),
        ),
      ),
    );
  }
}

一切正常,但动画效果很好。

编辑:我尝试添加一个键使其与众不同,但仍然没有动画。

class ColumnArticle extends StatelessWidget {
  final List<News> _news;
  final int _currentIndex;

  ColumnArticle(this._news, this._currentIndex);

  @override
  Widget build(BuildContext context) {
    return Column(
      key: ValueKey<int>(_currentIndex),
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: <Widget>[
        Text(
          _news[_currentIndex].title,
          textAlign: TextAlign.left,
          style: TextStyle(
            fontSize: 20.0,
          ),
        ),
        SizedBox(
          height: 10.0,
        ),
        Text(
          _news[_currentIndex].desc,
          style: TextStyle(
            fontSize: 14.0,
          ),
        ),
      ],
    );
  }
}

2 个答案:

答案 0 :(得分:1)

您的问题可能是here中所述的小部件类型。

  

如果“新”子代与“旧”子代具有相同的小部件类型和键,   但使用不同的参数,则AnimatedSwitcher不会执行   由于就框架而言,   它们是相同的小部件,并且现有的小部件可以使用   新参数。要强制进行过渡,请在   您希望被视为唯一的每个子小部件(通常是一个   小部件数据上的ValueKey,用于将该子项与   其他)。

您可以为News小部件设置单独的键,以使其唯一。如本例所示:

Column(
  children: <Widget>[
     AnimatedSwitcher(
         duration: const Duration(milliseconds: 500),

         child: Text(
             '$_count',
             // This key causes the AnimatedSwitcher to interpret this as a "new"
             // child each time the count changes, so that it will begin its animation
             // when the count changes.
             key: ValueKey<int>(_count),
         ),
     ),
     RaisedButton(
          child: const Text('Increment'),
          onPressed: () {
            setState(() {
              _count += 1;
            });
          },
     ),
])

答案 1 :(得分:1)

之所以会发生这种情况,是因为AnimatedSwitcher会随时添加动画 ,并使用不同的子引用对其进行重建。但是,在小部件生命周期中,您始终以ColumnArticle作为子级,因此实际上并没有交换任何小部件类型,这就是ValueKey发挥作用的地方。

您可以将索引用作密钥的参考,但确保它确实发生了更改,否则它将无法正常工作,您还需要将其传递给您的ColumnArticle库小部件(super)。

因此,您的ColumnArticle应该如下所示:

class ColumnArticle extends StatelessWidget {
  final List<News> _news;
  final int _currentIndex;

  ColumnArticle(this._news, this._currentIndex) : super(key: ValueKey<int>(_currentIndex));

  ...
}