通过动画使小部件越过另一个

时间:2020-10-27 19:24:51

标签: flutter flutter-layout flutter-animation

我是Flutter的新手,需要帮助。我曾经使用Phonegap构建应用程序,但他们已停止提供服务。

我面临以下问题:我正在尝试创建一个带有按钮的容器。按下按钮时,容器必须在1秒钟内充满(动画)屏幕。 因此,必须将其填充到底部的条形之前,不得超过底部。

请参见示例:另一个容器(绿色)下方的容器(橙色)是列表视图。

我尝试使用多个小部件(Column,ListView,Container),但没有结果。有人可以帮我这个忙吗?我应该使用哪个小部件?任何建议都欢迎。

example

1 个答案:

答案 0 :(得分:0)

您可以实现如下所示的示例:

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  double unexpandedTileHeight = 200.0;
  bool isExpandedMode = false;
  int _bottomNavIndex = 0;
  final double initialUnexpandedTileHeight = 200.0;
  final double roundedButtonSize = 48.0;
  final double bottomBarSize = 64.0;
  AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 450));
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Stack(
          fit: StackFit.expand,
          children: [
            MainPage(),
            AnimatedPositioned(
              duration: Duration(milliseconds: 200),
              top: unexpandedTileHeight,
              left: 0,
              right: 0,
              bottom: 0,
              child: OverlayPage(),
            ),
            AnimatedPositioned(
                duration: Duration(milliseconds: 200),
                left: MediaQuery.of(context).size.width / 2 -
                    roundedButtonSize / 2,
                top: unexpandedTileHeight -
                    (isExpandedMode
                        ? roundedButtonSize + 4
                        : roundedButtonSize / 2),
                child: RawMaterialButton(
                  fillColor: Colors.white,
                  constraints: BoxConstraints.tightFor(
                      width: roundedButtonSize, height: roundedButtonSize),
                  onPressed: () {
                    isExpandedMode
                        ? setState(() {
                            isExpandedMode = false;
                            unexpandedTileHeight = initialUnexpandedTileHeight;
                            _animationController.reverse();
                          })
                        : setState(() {
                            isExpandedMode = true;
                            var mediaQueryData = MediaQuery.of(context);
                            unexpandedTileHeight = mediaQueryData.size.height -
                                bottomBarSize -
                                mediaQueryData.padding.top -
                                mediaQueryData.padding.bottom;
                            _animationController.forward();
                          });
                  },
                  shape: StadiumBorder(),
                  child: AnimatedIcon(
                    icon: AnimatedIcons.list_view,
                    progress: _animationController,
                  ),
                ))
          ],
        ),
      ),
      bottomNavigationBar: SizedBox(
        height: bottomBarSize,
        child: BottomNavigationBar(
          backgroundColor: Colors.white,
          currentIndex: _bottomNavIndex,
          onTap: (index) => setState(() {
            _bottomNavIndex = index;
          }),
          type: BottomNavigationBarType.fixed,
          items: [
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              label: 'Home',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.radio),
              label: 'Radio',
            ),
          ],
        ),
      ),
    );
  }
}

class OverlayPage extends StatelessWidget {
  const OverlayPage({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.orange,
    );
  }
}

class MainPage extends StatelessWidget {
  const MainPage({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(
        horizontal: 16.0,
      ),
      color: Colors.green,
      child: Column(
        children: [
          SizedBox(height: 16),
          Text('bla bla bla'),
          SizedBox(height: 24),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                Icons.photo,
                size: 56,
              ),
              SizedBox(width: 24),
              Text(
                'bla bla bla',
                style: TextStyle(fontSize: 18),
              ),
            ],
          ),
          SizedBox(height: 100),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                'dasdadasds',
                style: TextStyle(fontSize: 18),
              ),
              Text(
                'fdsfsdf',
                style: TextStyle(fontSize: 18),
              ),
            ],
          ),
          SizedBox(height: 16),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                'dasdadasds',
                style: TextStyle(fontSize: 18),
              ),
              Text(
                'fdsfsdf',
                style: TextStyle(fontSize: 18),
              ),
            ],
          ),
          SizedBox(height: 16),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                'dasdadasds',
                style: TextStyle(fontSize: 18),
              ),
              Text(
                'fdsfsdf',
                style: TextStyle(fontSize: 18),
              ),
            ],
          ),
          SizedBox(height: 16),
        ],
      ),
    );
  }
}

Screenshot opened

Screenshot closed