Flutter在項(xiàng)目中使用動(dòng)畫不使用包實(shí)現(xiàn)詳解
前言
動(dòng)畫對(duì)于 web 和移動(dòng)應(yīng)用程序都非常重要。但是在移動(dòng)應(yīng)用程序中不應(yīng)該使用夸張的動(dòng)畫。簡(jiǎn)單但是很多動(dòng)畫使你的應(yīng)用程序更好用。以至于當(dāng)你點(diǎn)擊一個(gè)按鈕時(shí),一種平滑的感覺或者頁面過渡都會(huì)影響到你。
正文
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:
首先,我們創(chuàng)建一個(gè)名為 CustomButton 的 StatewWidget。我們將在應(yīng)用程序的任何地方使用這個(gè)按鈕。也許寬度,里面的文字會(huì)改變。在最后一個(gè)子部分之后,我們將設(shè)計(jì)我們的按鈕。(我不想在這里占用太多的空間,你可以在文章的最后找到完成項(xiàng)目的源代碼)。
在我們看到模擬器中的動(dòng)畫之前,我們還有一個(gè)場(chǎng)景。當(dāng)我們按下這個(gè)按鈕時(shí),我們希望出現(xiàn)一個(gè)彈出窗口。彈出窗口突然出現(xiàn)在 Flutter 的屏幕上。同樣,我們可以通過使用動(dòng)畫給人一種柔軟的感覺。請(qǐng)確保您的應(yīng)用程序?qū)⒏訉I(yè)和吸引眼球的方式:)
return showGeneralDialog( context: context, pageBuilder: (context, animation, secondaryAnimation) { return ScaleTransition( scale: Tween<double>(begin: 0.5, end: 1).animate(animation), child: AlertDialog(
只要將這些 widget 包裝在 AlertDialog 的頂部,您就會(huì)看到一個(gè)非常漂亮的效果
2 想要一個(gè)像 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; }); }, )), ); } }
當(dāng) isFavorite 狀態(tài)改變時(shí),動(dòng)畫將出現(xiàn),按鈕的內(nèi)部將被涂成紅色。這里最重要的部分是關(guān)鍵作業(yè)。如果您不這樣做,系統(tǒng)將檢測(cè)到兩個(gè)相同的動(dòng)畫將不會(huì)出現(xiàn)。
3 動(dòng)畫頁面過渡
實(shí)際上,這里有一個(gè)包依賴項(xiàng)。不過別擔(dān)心,這是必要的。因?yàn)樵?Flutter Navigator.push() 等方法現(xiàn)在是原始的。我強(qiáng)烈推薦使用 GoRoute 或 AutoRoute。在本文中,我們將討論 GoRoute 中可用的動(dòng)畫。
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(), ); }, ), ], ), ], );
下面是將執(zhí)行主要工作的方法 animationPage() 。我們用這種方法包裝相關(guān)頁面并完成工作。您可以通過更改 start: const Offset (-1,0)值來實(shí)現(xiàn)不同的動(dòng)畫。我想像書頁一樣過渡。這就是它看起來的樣子
此外,我想提出一個(gè)批評(píng)。如果不使用動(dòng)畫,頁面轉(zhuǎn)換在 Flutter 中是非常粗糙的。
4 動(dòng)畫文字
通過您現(xiàn)在將看到的動(dòng)畫,您可以在頁面首次打開時(shí)顯示可滾動(dòng)的文本。閑話少說,讓我們檢查一下代碼,然后討論一下我們能做些什么。
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, ), ); } }
我想讓你注意兩件事。第一個(gè)是。.正向()方法正向()方法。這表示當(dāng)打開該頁面時(shí),該動(dòng)畫僅顯示一次。如果用 repeat() 替換它,它將是連續(xù)的。第二,軸對(duì)齊參數(shù)。我做了這個(gè) -1。文本從左到右。如果我做 1,它會(huì)是相反的。這是我最喜歡的動(dòng)畫。您可以將此動(dòng)畫應(yīng)用于除 Text 之外的許多其他 widget 。
5 更改/閃動(dòng)文本樣式
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() 。這意味著它將連續(xù)運(yùn)行。您可以在要顯示給用戶的文本、按鈕、卡片 widget 中顯示這一點(diǎn)。也許是競(jìng)選宣言。我把你留給你的想象力,所有你要做的就是復(fù)制動(dòng)畫相關(guān)的代碼,并發(fā)揮他們:)
代碼
以上就是Flutter在項(xiàng)目中使用動(dòng)畫不使用包實(shí)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于Flutter項(xiàng)目動(dòng)畫使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決Android ListView數(shù)據(jù)為空及加載錯(cuò)誤的方法
這篇文章主要為大家提供了一個(gè)解決Android ListView數(shù)據(jù)為空及加載錯(cuò)誤的方法,感興趣的小伙伴們可以參考一下2016-02-02Android Studio使用小技巧:布局預(yù)覽時(shí)填充數(shù)據(jù)
這篇文章主要介紹了Android Studio使用小技巧:布局預(yù)覽時(shí)填充數(shù)據(jù),本文給出了代碼操作實(shí)例和效果圖例,需要的朋友可以參考下2015-05-05Android仿簡(jiǎn)書動(dòng)態(tài)searchview搜索欄效果
這篇文章主要為大家詳細(xì)介紹了Android仿簡(jiǎn)書動(dòng)態(tài)searchview效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06android bitmap compress(圖片壓縮)代碼
android bitmap compress(圖片壓縮)代碼,需要的朋友可以參考一下2013-06-06Android viewpager無限輪播獲取網(wǎng)絡(luò)圖片功能
這篇文章主要為大家詳細(xì)介紹了Android viewpager無限輪播獲取網(wǎng)絡(luò)圖片功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09基于Android實(shí)現(xiàn)數(shù)獨(dú)游戲
這篇文章主要為大家詳細(xì)介紹了基于Android實(shí)現(xiàn)數(shù)獨(dú)游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Android 取得狀態(tài)欄、任務(wù)欄高度的小例子
Android 取得狀態(tài)欄、任務(wù)欄高度的小例子,需要的朋友可以參考一下2013-05-05