Flutter:Stack 中的 AnimatedSwitcher 未在所需位置设置动画
Flutter: AnimatedSwitcher in Stack not animating in desired position
我正在尝试在 Stack
中使用 AnimatedSwitcher
。这会导致动画出现非常奇怪的行为。它在我的 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())
],
),
),
);
}
}
在屏幕某处的点击事件中会产生以下行为:
知道为什么左上角的红框没有动画,但只有在动画结束后才会出现吗?
正如@Marino Zorilla 指出的那样,问题在于我为动画小部件指定的唯一键。一旦我删除了这个键并将“空”Container
(对于我的三元操作的 false-condition)更改为 SizedBox
,它就会按预期工作。
显然,这与 flutter 的内部工作方式有关(当 element tree 和 widget tree 进行比较以确定哪个小部件需要重建)。如果小部件更改为不同的类型(例如在我的情况下从 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(),
)
],
)),
);
}
}
我正在尝试在 Stack
中使用 AnimatedSwitcher
。这会导致动画出现非常奇怪的行为。它在我的 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())
],
),
),
);
}
}
在屏幕某处的点击事件中会产生以下行为:
知道为什么左上角的红框没有动画,但只有在动画结束后才会出现吗?
正如@Marino Zorilla 指出的那样,问题在于我为动画小部件指定的唯一键。一旦我删除了这个键并将“空”Container
(对于我的三元操作的 false-condition)更改为 SizedBox
,它就会按预期工作。
显然,这与 flutter 的内部工作方式有关(当 element tree 和 widget tree 进行比较以确定哪个小部件需要重建)。如果小部件更改为不同的类型(例如在我的情况下从 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(),
)
],
)),
);
}
}