简体   繁体   English

窗口小部件如何使动画向下滑动?

[英]How to do widget slide down animation in flutter?

I want to do a slide-down animation for a widget. 我想为小部件做一个slide-down动画。 I've seen a lot of examples from the internet but nothing meets my requirements. 我从互联网上看到了很多例子,但是没有什么可以满足我的要求。 Here is what I need. 这就是我所需要的。 Below is a custom widget I made. 以下是我制作的自定义小部件。

Widget Toast(String content, ToastType type) {
  return Column(
    children: <Widget>[
      Padding(
        padding: const EdgeInsets.all(50),
        child: Card(
          elevation: 10,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
          color: ToastColors[type.index],
          child: Padding(
            padding: const EdgeInsets.only(left: 15, right: 20, top: 10, bottom: 10),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                ToastIcons[type.index],
                SizedBox(
                  width: 15,
                ),
                Flexible(
                  child: Text(
                    content,
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.w400,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    ],
  );
}

It's a toast layout. 这是一个烤面包的布局。 I want this to be accessible from anywhere within the app. 我希望可以从应用程序中的任何位置进行访问。 That's why I've created separate dart file for this. 这就是为什么我为此创建了单独的dart文件的原因。

What I want? 我想要的是? When the widget is shown, I want the toast layout to slide down. 显示小部件时,我希望烤面包布局向下滑动。 I don't want to loop or reverse the animation. 我不想循环播放或反转动画。 After the animation is completed, the widget must stay still in the end position. 动画完成后,小部件必须保持在最终位置。

I'm extrapolating from your description of your code that you want to be able to create a toast that slides down from the top of the screen, and that you want to be able to create it from anywhere. 我从对代码的描述中推断出,您希望能够创建从屏幕顶部向下滑动的Toast,并且希望能够在任何地方创建它。

You're in luck, flutter has a function for that! 您很幸运,颤振具有此功能! showGeneralDialog is what you're looking for. showGeneralDialog是您要寻找的。

Here's an example: 这是一个例子:

import 'package:flutter/material.dart';

main() => runApp(TheApp());

class TheApp extends StatefulWidget {
  @override
  _TheAppState createState() => _TheAppState();
}

class _TheAppState extends State<TheApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        floatingActionButton: Builder(
          builder: (context) {
            return FloatingActionButton(
              child: Icon(
                Icons.add,
              ),
              onPressed: () {
                bool wasCompleted = false;
                showGeneralDialog(
                  context: context,
                  barrierDismissible: true,
                  transitionDuration: Duration(milliseconds: 500),
                  barrierLabel: MaterialLocalizations.of(context).dialogLabel,
                  barrierColor: Colors.black.withOpacity(0.5),
                  pageBuilder: (context, _, __) {
                    return TheToast();
                  },
                  transitionBuilder: (context, animation, secondaryAnimation, child) {
                    if (animation.status == AnimationStatus.completed) {
                      wasCompleted = true;
                    }

                    if (wasCompleted) {
                      return FadeTransition(
                        opacity: animation,
                        child: child,
                      );
                    } else {
                      return SlideTransition(
                        position: CurvedAnimation(
                          parent: animation,
                          curve: Curves.easeOut,
                        ).drive(Tween<Offset>(begin: Offset(0, -1.0), end: Offset.zero)),
                        child: child,
                      );
                    }
                  },
                );
              },
            );
          },
        ),
        body: Container(),
      ),
    );
  }
}

class TheToast extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Card(
        color: Colors.white,
        child: Padding(
          padding: EdgeInsets.all(10),
          child: Text(
            "I'm a Toast",
            style: TextStyle(color: Colors.black),
          ),
        ),
      ),
    );
  }
}

You could make your own function similar to showGeneralDialog (maybe showToast) and call that with the appropriate text. 您可以使自己的函数类似于showGeneralDialog(也许是showToast),并使用适当的文本进行调用。 I've also made the toast fade out after the animation; 动画结束后,我也使吐司淡了。 if you just want it to slide back up that's even simpler and you can get rid of that part of the transition logic. 如果您只想让它向上滑动,那会更加简单,并且可以摆脱过渡逻辑的这一部分。 I've also made the toast disappear when the background is tapped but you could disable that and instead call Navigator.pop(context) when you want the dialog to be hidden instead. 当您点按背景时,我也使吐司消失了,但是您可以禁用该吐司,而当您想隐藏对话框时,可以调用Navigator.pop(context)。

You could also do this directly with Overlay entries but this is definitely simpler. 您也可以使用“覆盖”条目直接执行此操作,但这绝对简单。

Nvm. Nvm。 I figured it out. 我想到了。 First I created a StatefulWidget and used it as a child in showToastWidget function. 首先,我创建了一个StatefulWidget ,并将其用作showToastWidget函数中的子showToastWidget

Here is the StatefulWidget class 这是StatefulWidget

import 'package:flutter/material.dart';

class SlideToast extends StatefulWidget {
  final Widget _toast;

  SlideToast(this._toast);

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

class _SlideToastState extends State<SlideToast> with TickerProviderStateMixin {
  AnimationController _controller;
  Animation<Offset> _offsetFloat;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 350),
    );

    _offsetFloat =
        Tween(begin: Offset(0.0, -0.03), end: Offset.zero).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Curves.fastOutSlowIn,
      ),
    );

    _offsetFloat.addListener(() {
      setState(() {});
    });

    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
      position: _offsetFloat,
      child: widget._toast,
    );
  }
}

Required function , enum , list 所需functionenumlist

enum ToastType { Info, Warning, Success, Error }

const List<Color> ToastColors = [
  Colors.blue,
  Colors.orange,
  Colors.green,
  Colors.redAccent
];

const List<Icon> ToastIcons = [
  Icon(
    Icons.info,
    color: Colors.white,
  ),
  Icon(
    Icons.info,
    color: Colors.white,
  ),
  Icon(
    Icons.check_circle,
    color: Colors.white,
  ),
  Icon(
    Icons.error,
    color: Colors.white,
  )
];

Widget Toast(String content, ToastType type) {
  return Column(
    children: <Widget>[
      Padding(
        padding: const EdgeInsets.only(top: 85),
        child: Card(
          elevation: 10,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
          color: ToastColors[type.index],
          child: Padding(
            padding:
                const EdgeInsets.only(left: 15, right: 20, top: 10, bottom: 10),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                ToastIcons[type.index],
                SizedBox(
                  width: 15,
                ),
                Flexible(
                  child: Text(
                    content,
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.w400,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    ],
  );
}

Finally call showToastWidget like this 最后像这样调用showToastWidget

showToastWidget(
   Toast('Hello World!!!', ToastType.Warning),
   duration: Duration(seconds: 1),
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM