#flutter #animation
Вопрос:
Я пытаюсь использовать AnimatedSwitcher
внутреннее Stack
. Это приводит к очень странному поведению анимации. Он анимирует соответствующий дочерний виджет (красное поле в моем случае) в центре моего Stack
экрана, и по завершении он привязывается к верхнему левому углу моего экрана(именно там я также хотел бы, чтобы анимация происходила). Когда я переключаюсь обратно, происходит то же самое странное поведение.
Мой код выглядит следующим образом:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: Home()));
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
bool _showMenu = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
GestureDetector(
onTap: () => setState(() => _showMenu = !_showMenu),
child: SizedBox.expand(
child: Container(
color: Colors.yellow,
),
),
),
AnimatedSwitcher(
duration: Duration(milliseconds: 500),
child: _showMenu
? Container(
key: UniqueKey(),
height: 200,
width: 200,
color: Colors.red,
)
: Container())
],
),
),
);
}
}
Что приводит к следующему поведению при нажатии-событии где-то на экране:
Есть идеи, почему красное поле не анимируется в левом верхнем углу, а появляется там только после завершения анимации?
Комментарии:
1. Ваш ключ должен быть уникальным окончательным, а не повторять один и тот же снова и снова.
2. хорошо, я думал, что использую уникальный ключ, добавляя
UniqueKey
его в свою анимациюContainer
. Если я удалю этот ключ, он полностью прекратит анимацию (даже если он действительно перестанет неловко менять положение, как и раньше)… не могли бы вы предложить, как это решить?3. вам нужен уникальный ключ… но должен быть заключительный глобальный по этому классу… потому что каждый раз, когда метод сборки вызывается снова, тот, который у вас есть, отбрасывается и создается снова
4. если я добавлю
final key = UniqueKey();
уровень класса, он все равно поменяется местами… что я упускаю?
Ответ №1:
Проблема заключается, как указал @Marino Zorilla, в уникальном ключе, который я указал для своего анимирующего виджета. Как только я удалил этот ключ, а также изменил «пустой» Container
(для ложного условия моей троичной операции) на a SizedBox
, он работает по желанию.
По-видимому, это связано с тем, как flutter работает внутри (когда дерево элементов и дерево виджетов сравниваются, чтобы определить, какие виджеты необходимо перестроить). Если виджет изменится на другой тип (как в моем случае с Container
на SizedBox
), для flutter не требуется ключ, чтобы знать, что этот виджет необходимо перестроить.
Правильный код выглядит следующим образом:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: Home()));
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
bool _showBox = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
GestureDetector(
onTap: () => setState(() => _showBox = !_showBox),
child: SizedBox.expand(
child: Container(
color: Colors.yellow,
),
),
),
AnimatedSwitcher(
duration: Duration(milliseconds: 500),
child: _showBox
? Container(
height: 200.0,
width: 200.0,
color: Colors.red,
)
: SizedBox(),
)
],
)),
);
}
}