阅读 59

Flutter 在项目中使用动画(不使用包)

Flutter 在项目中使用动画(不使用包)

前言

动画对于 web 和移动应用程序都非常重要。但是在移动应用程序中不应该使用夸张的动画。简单但是很多动画使你的应用程序更好用。以至于当你点击一个按钮时,一种平滑的感觉或者页面过渡都会影响到你。

正文

1 按下按钮柔软的感觉

class _CustomButtonState extends State<CustomButton>     with SingleTickerProviderStateMixin {   late double _scale;   late AnimationController _controller;   @override   void initState() {     super.initState();     _controller = AnimationController(       vsync: this,       duration: const Duration(milliseconds: 350),       lowerBound: 0.0,       upperBound: 0.1,     )..addListener(() {         setState(() {});       });   }   @override   void dispose() {     _controller.dispose();     super.dispose();   }   void _tapDown(TapDownDetails details) {     _controller.forward();   }   void _tapUp(TapUpDetails details) {     _controller.reverse();   }   @override   Widget build(BuildContext context) {     _scale = 1 - _controller.value;     return GestureDetector(       onTap: widget.onTap,       onTapDown: _tapDown,       onTapUp: _tapUp,       child: Transform.scale(         scale: _scale,         child: 复制代码

首先,我们创建一个名为 CustomButton 的 StatewWidget。我们将在应用程序的任何地方使用这个按钮。也许宽度,里面的文字会改变。在最后一个子部分之后,我们将设计我们的按钮。(我不想在这里占用太多的空间,你可以在文章的最后找到完成项目的源代码)。

在我们看到模拟器中的动画之前,我们还有一个场景。当我们按下这个按钮时,我们希望出现一个弹出窗口。弹出窗口突然出现在 Flutter 的屏幕上。同样,我们可以通过使用动画给人一种柔软的感觉。请确保您的应用程序将更加专业和吸引眼球的方式:)

return showGeneralDialog(     context: context,     pageBuilder: (context, animation, secondaryAnimation) {       return ScaleTransition(         scale: Tween<double>(begin: 0.5, end: 1).animate(animation),         child: AlertDialog( 复制代码

只要将这些 widget 包装在 AlertDialog 的顶部,您就会看到一个非常漂亮的效果

2 想要一个像 Instagram 一样的喜欢按钮吗?

class _FavoritesButtonState extends State<FavoritesButton>     with SingleTickerProviderStateMixin {   bool isFavorite = false;   late final AnimationController _controller = AnimationController(       vsync: this, duration: const Duration(milliseconds: 300));   @override   Widget build(BuildContext context) {     return Container(       height: 10.h,       width: 10.w,       decoration: const BoxDecoration(         shape: BoxShape.circle,         color: Colors.white,         boxShadow: [           BoxShadow(             offset: Offset(0, 1),             color: Colors.grey,             blurRadius: 1,           ),         ],       ),       child: AnimatedBuilder(           animation: _controller,           builder: (context, child) => GestureDetector(                 child: isFavorite                     ? AnimatedSwitcher(                         switchInCurve: Curves.easeInOutBack,                         transitionBuilder: (child, animation) =>                             ScaleTransition(                               scale: animation,                               child: child,                             ),                         duration: const Duration(milliseconds: 300),                         child: Icon(                           Icons.favorite,                           size: 3.7.h,                           color: Colors.red,                           key: const ValueKey('isFav'),                         ))                     : AnimatedSwitcher(                         switchInCurve: Curves.easeInOutBack,                         transitionBuilder: (child, animation) =>                             ScaleTransition(                           scale: animation,                           child: child,                         ),                         duration: const Duration(milliseconds: 300),                         child: Icon(                           Icons.favorite_border_outlined,                           size: 3.7.h,                           color: Colors.grey,                           key: const ValueKey('isNotFav'),                         ),                       ),                 onTap: () {                   setState(() {                     isFavorite = !isFavorite;                   });                 },               )),     );   } } 复制代码

当 isFavorite 状态改变时,动画将出现,按钮的内部将被涂成红色。这里最重要的部分是关键作业。如果您不这样做,系统将检测到两个相同的动画将不会出现。

3 动画页面过渡

实际上,这里有一个包依赖项。不过别担心,这是必要的。因为在 Flutter Navigator.push() 等方法现在是原始的。我强烈推荐使用 GoRoute 或 AutoRoute。在本文中,我们将讨论 GoRoute 中可用的动画。

import 'package:animations/view/empty/empty_view.dart'; import 'package:animations/view/home/home_view.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; animationPage({required GoRouterState state, required Widget route}) =>     CustomTransitionPage<void>(       key: state.pageKey,       child: route,       transitionsBuilder: (BuildContext context, Animation<double> animation,               Animation<double> secondaryAnimation, Widget child) =>           SlideTransition(         position: animation.drive(           Tween<Offset>(             begin: const Offset(-1, 0),             end: Offset.zero,           ).chain(CurveTween(curve: Curves.fastOutSlowIn)),         ),         child: child,       ),     ); final routes = GoRouter(   initialLocation: '/home',   debugLogDiagnostics: true,   routes: [     GoRoute(       path: '/home',       pageBuilder: (context, state) {         return animationPage(           state: state,           route: const HomeView(),         );       },       routes: [         GoRoute(           path: 'empty',           pageBuilder: (context, state) {             return animationPage(               state: state,               route: const EmptyView(),             );           },         ),       ],     ),   ], ); 复制代码

下面是将执行主要工作的方法 animationPage() 。我们用这种方法包装相关页面并完成工作。您可以通过更改 start: const Offset (-1,0)值来实现不同的动画。我想像书页一样过渡。这就是它看起来的样子

此外,我想提出一个批评。如果不使用动画,页面转换在 Flutter 中是非常粗糙的。

4 动画文字

通过您现在将看到的动画,您可以在页面首次打开时显示可滚动的文本。闲话少说,让我们检查一下代码,然后讨论一下我们能做些什么。

class _AnimatedTextState extends State<AnimatedText>     with TickerProviderStateMixin {   late final AnimationController _controller = AnimationController(     duration: const Duration(seconds: 3),     vsync: this,   )..forward();   late final Animation<double> _animation = CurvedAnimation(     parent: _controller,     curve: Curves.fastOutSlowIn,   );   @override   void dispose() {     _controller.dispose();     super.dispose();   }   @override   Widget build(BuildContext context) {     return SizeTransition(       sizeFactor: _animation,       axis: Axis.horizontal,       axisAlignment: -1,       child: CustomText(         widget.text,         textStyle: widget.textStyle,       ),     );   } } 复制代码

我想让你注意两件事。第一个是。.正向()方法正向()方法。这表示当打开该页面时,该动画仅显示一次。如果用 repeat() 替换它,它将是连续的。第二,轴对齐参数。我做了这个 -1。文本从左到右。如果我做 1,它会是相反的。这是我最喜欢的动画。您可以将此动画应用于除 Text 之外的许多其他 widget 。

5 更改/闪动文本样式

class ChangingText extends StatefulWidget {   const ChangingText(this.text, {super.key});   final String text;   @override   State<ChangingText> createState() => _ChangingTextState(); } class _ChangingTextState extends State<ChangingText>     with TickerProviderStateMixin {   late AnimationController _controller;   late TextStyleTween _styleTween;   late CurvedAnimation _curvedAnimation;   @override   void initState() {     super.initState();     _controller = AnimationController(       duration: const Duration(milliseconds: 750),       vsync: this,     )..repeat(reverse: true);     _styleTween = TextStyleTween(       begin: GoogleFonts.poppins(         fontSize: 15.sp,         color: AppConstants.java,       ),       end: TextStyle(         fontSize: 15.sp,         color: AppConstants.bittersweet,       ),     );     _curvedAnimation = CurvedAnimation(       parent: _controller,       curve: Curves.elasticInOut,     );   }   @override   void dispose() {     _controller.dispose();     super.dispose();   }   @override   Widget build(BuildContext context) {     return Center(       child: DefaultTextStyleTransition(         style: _styleTween.animate(_curvedAnimation),         child: CustomText(widget.text),       ),     );   } } 复制代码

我在这里使用了 repeat() 。这意味着它将连续运行。您可以在要显示给用户的文本、按钮、卡片 widget 中显示这一点。也许是竞选宣言。我把你留给你的想象力,所有你要做的就是复制动画相关的代码,并发挥他们:)


作者:会煮咖啡的猫
链接:https://juejin.cn/post/7166983362446360612


文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐