Mar*_*din 8 dart flutter 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),
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
一切正常,但动画。
编辑:我尝试添加一个键以使其不同但仍然没有动画。
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,
),
),
],
);
}
}
Run Code Online (Sandbox Code Playgroud)
Mig*_*ivo 12
这是因为在AnimatedSwitcher将添加动画任何时候它被重建了不同的子参考。但是,在您的小部件生命周期中,您始终将 aColumnArticle作为子项使用,因此实际上并没有交换任何小部件类型,这就是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));
...
}
Run Code Online (Sandbox Code Playgroud)
传递具有不同属性的相同类型的小部件不会触发动画,因为它们是框架的相同小部件。说明中也有提到。
如果“新”子项与“旧”子项具有相同的小部件类型和键,但具有不同的参数,则 AnimatedSwitcher 不会在它们之间进行转换,因为就框架而言,它们是相同的小部件和可以使用新参数更新现有小部件。要强制发生转换,请在您希望被视为唯一的每个子小部件上设置一个键(通常是小部件数据上的 ValueKey,可将这个子小部件与其他小部件区分开来)。
这是AnimatedSwitcher检查是否设置动画的代码:
if (hasNewChild != hasOldChild ||
hasNewChild && !Widget.canUpdate(widget.child, _currentEntry.widgetChild)) {
// Child has changed, fade current entry out and add new entry.
_childNumber += 1;
_addEntryForNewChild(animate: true);
}
Run Code Online (Sandbox Code Playgroud)
这是canUpdate框架中的静态方法:
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,您可以News根据小部件的不同属性(例如文本、计数、值)为小部件设置单独的键。ValueKey<T>就是为了那个。
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;
});
},
),
])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4935 次 |
| 最近记录: |