Flutter AnimatedCrossFade 搞乱了小部件格式

Flutter AnimatedCrossFade messes up widget formatting

我正在尝试使用 AnimatedCrossFade 小部件创建流畅的动画,但我发现了 2 个问题:

按钮尺寸在动画期间发生变化和扩展。

期望的结果是两个按钮都与父按钮的宽度相匹配,并且颜色和文本的变化过渡平滑,但实际情况是这样的。

带有 InputDecoration 笔触的 TextField 变得更细

我有多个要在页面中使用的 TextField 小部件,但有些需要在其中设置动画。问题是当我放置 TextField AnimatedCrossFade 小部件中,底线变得更细,使布局看起来很糟糕。这是 TextFieldAnimatedCrossFade 内部(顶部)和外部(底部)的对比。

此代码示例应该足以重现我要解释的内容。

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _isExpanded = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView(
        padding: EdgeInsets.symmetric(horizontal: 60, vertical: 60),
        children: [
          ElevatedButton(
            child: Text(_isExpanded ? "Collapse" : "Expand"),
            onPressed: () {
              setState(() {
                _isExpanded = !_isExpanded;
              });
            },
          ),
          AnimatedCrossFade(
            crossFadeState: _isExpanded
                ? CrossFadeState.showFirst
                : CrossFadeState.showSecond,
            duration: const Duration(seconds: 1),
            firstChild: TextField(
              decoration: InputDecoration(
                hintText: "Text",
              ),
            ),
            secondChild: SizedBox.shrink(),
          ),
          TextField(
            decoration: InputDecoration(
              hintText: "Text",
            ),
          ),
          AnimatedCrossFade(
            crossFadeState: !_isExpanded
                ? CrossFadeState.showFirst
                : CrossFadeState.showSecond,
            duration: Duration(seconds: 1),
            firstChild: ElevatedButton(
              child: Text("Button 1"),
              onPressed: () {},
            ),
            secondChild: ElevatedButton(
              child: Text("Button 2"),
              style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all(Colors.red),
              ),
              onPressed: () {},
            ),
          ),
        ],
      ),
    );
  }
}

希望这就是你想要的?

我认为要处理这种情况,您需要使用 layoutBuilder of AnimatedCrossFade 如果你点击 layoutBuilder 你可以找到详细信息。

已更新 wrap with padding to solve TextFiledFormat,更多可以使用decoration

要使用最大宽度我是这样使用的

  AnimatedCrossFade(
            crossFadeState: _isExpanded
                ? CrossFadeState.showFirst
                : CrossFadeState.showSecond,
            duration: const Duration(seconds: 1),
            firstChild: Padding(
              padding: const EdgeInsets.symmetric(vertical: 4),
              child: TextField(
                key: ValueKey("text1"),
                decoration: InputDecoration(
                  hintText: "Text1",
                ),
              ),
            ),
            secondChild: SizedBox.shrink(),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 4),
            child: TextField(
              key: ValueKey("text2"),
              decoration: InputDecoration(
                hintText: "Text",
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 4.0),
            child: AnimatedCrossFade(
              crossFadeState: !_isExpanded
                  ? CrossFadeState.showFirst
                  : CrossFadeState.showSecond,
              duration: Duration(seconds: 1),
              alignment: Alignment.center,
              layoutBuilder:
                  (topChild, topChildKey, bottomChild, bottomChildKey) {
                return topChild;
              },
              secondChild: ElevatedButton(
                child: Text("Button 2"),
                style: ButtonStyle(
                  backgroundColor: MaterialStateProperty.all(Colors.red),
                ),
                onPressed: () {},
              ),
              firstChild: ElevatedButton(
                child: Text("Button 1"),
                style: ButtonStyle(
                  backgroundColor: MaterialStateProperty.all(Colors.red),
                ),
                onPressed: () {},
              ),
            ),
          ),

在 layoutBuilder 中获取用 Center 包裹的按钮的默认大小

  layoutBuilder:
                (topChild, topChildKey, bottomChild, bottomChildKey) {
              return topChild;
            },