Flutter AnimatedCrossFade портит форматирование виджетов

Я пытаюсь создать плавную анимацию с помощью виджета AnimatedCrossFade, но заметил две проблемы:

Размер кнопки изменяется и расширяется во время анимации.

Желаемый результат состоит в том, чтобы обе кнопки соответствовали ширине родительского элемента и чтобы цвет и текст менялись плавно, но вот что происходит.

  • Без AnimatedCrossFade, кнопка 1 выглядит следующим образом :

  • Если я заключу его в виджет AnimatedCrossFade, кнопка 1 будет выглядеть так:

  • Пока происходит переход, он выглядит так:

TextField с обводкой InputDecoration становится тоньше

У меня есть несколько виджетов TextField, которые я хочу использовать на странице, но некоторые из них нужно анимировать. Проблема в том, что когда я помещаю TextField внутри виджета AnimatedCrossFade , нижняя строка становится тоньше, из-за чего макет выглядит ужасно. Вот сравнение того, как TextField выглядит внутри AnimatedCrossFade (вверху) и за его пределами (внизу).

  • Так выглядит макет после анимации.

  • Но это должно выглядеть так.

Этого образца кода должно быть достаточно, чтобы воссоздать то, что я пытаюсь объяснить.

      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: () {},
            ),
          ),
        ],
      ),
    );
  }
}

1 ответ

Надеюсь, это то, что ты хочешь?

Я думаю, чтобы справиться с этим случаем, вам нужно использовать AnimatedCrossFade если вы нажмете на layoutBuilder вы можете найти подробности.

Чтобы использовать максимальную ширину, я использовал вот так

         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

        layoutBuilder:
                (topChild, topChildKey, bottomChild, bottomChildKey) {
              return topChild;
            },
Другие вопросы по тегам