在Flutter中使用一致的按钮位置实现平滑过渡动画

irlmq6kh  于 2023-10-22  发布在  Flutter
关注(0)|答案(1)|浏览(169)

我有一个Flutter应用程序,它有一个AnimatedSwitcher小部件,可以在两个容器之间转换。过渡效果很好,但我希望动画小部件外部的按钮能够平滑地跟随过渡而不跳跃。
下面是当前代码:

import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  bool _isOn = false;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,
      children: [
        ElevatedButton(
          onPressed: () {
            setState(() {
              _isOn = !_isOn;
            });
          },
          child: const Text('Toggle'),
        ),
        AnimatedSwitcher(
          duration: const Duration(milliseconds: 2000),
          child: _isOn
              ? Container(
                  key: const ValueKey('On'),
                  color: Colors.green,
                  height: 300,
                  width: 300,
                  child: const Text('On'),
                )
              : Container(
                  key: const ValueKey('Off'),
                  color: Colors.red,
                  height: 500,
                  width: 300,
                  child: const Text('Off'),
                ),
        ),
      ],
    );
  }
}

在这段代码中,我有一个MyApp小部件和一个MyWidget StatefulWidget。MyWidget包含一个基于切换按钮在两个容器之间转换的AnimatedSwitcher。
我想实现两个容器之间的平滑过渡动画(例如,淡入淡出,旋转),同时确保外部按钮在整个动画中保持一致的位置(例如,高度)。
在这里,我放置2个小部件与特定的高度,但我的真实的应用程序有不同的高度可能。
有没有人知道如何实现这一点?非常感谢您的帮助!

xienkqul

xienkqul1#

使用AnimatedSize将保持按钮在顶部,但对齐方式需要从默认center更改为topCenter

class MyWidget extends StatefulWidget {
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  bool _isOn = false;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        mainAxisSize: MainAxisSize.min,
        children: [
          ElevatedButton(
            onPressed: () {
              setState(() {
                _isOn = !_isOn;
              });
            },
            child: const Text('Toggle'),
          ),
          AnimatedSize(
            duration: const Duration(milliseconds: 2000),
            alignment: Alignment.topCenter,
            child: _isOn
                ? Container(
                    color: Colors.green,
                    height: 300,
                    width: 300,
                    child: const Text('On'),
                  )
                : Container(
                    color: Colors.red,
                    height: 500,
                    width: 300,
                    child: const Text('Off'),
                  ),
          ),
        ],
      ),
    );
  }
}

v0:你可以AnimatedContainer,它将动画。

class MyWidget extends StatefulWidget {
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  bool _isOn = false;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,
      children: [
        ElevatedButton(
          onPressed: () {
            setState(() {
              _isOn = !_isOn;
            });
          },
          child: const Text('Toggle'),
        ),
        AnimatedContainer(
            duration: const Duration(milliseconds: 2000),
            // key: const ValueKey('On'),
            color: _isOn ? Colors.green : Colors.red,
            height: _isOn ? 300 : 500,
            width: 300,
            child: Text(_isOn ? 'On' : 'Off'))
      ],
    );
  }
}

相关问题