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 IntentService實(shí)現(xiàn)原理及內(nèi)部代碼分享
android IntentService實(shí)現(xiàn)原理及內(nèi)部代碼分享,需要的朋友可以參考一下2013-06-06
Android 判斷當(dāng)前語言環(huán)境是否是中文環(huán)境
本文主要介紹了Android 判斷當(dāng)前語言環(huán)境是否是中文環(huán)境的方法。具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-04-04
Android模仿實(shí)現(xiàn)閑魚首頁的思路與方法
這篇文章主要給大家介紹了Android模仿實(shí)現(xiàn)閑魚首頁的思路與方法,文中通過示例代碼介紹的非常詳細(xì),并在文末給出了完整的代碼供大家參考學(xué)習(xí),需要的朋友們下面來一起看看吧。2017-04-04
Android中實(shí)現(xiàn)GPS定位的簡(jiǎn)單例子
這篇文章主要介紹了Android中實(shí)現(xiàn)GPS定位的簡(jiǎn)單例子,例子邏輯清晰,但相對(duì)簡(jiǎn)單了些,需要的朋友可以參考下2014-07-07
Android編程實(shí)現(xiàn)Dialog窗體監(jiān)聽的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)Dialog窗體監(jiān)聽的方法,結(jié)合實(shí)例形式分析了Android針對(duì)Dialog對(duì)話框窗體事件監(jiān)聽與響應(yīng)相關(guān)操作技巧,需要的朋友可以參考下2017-03-03
Android實(shí)現(xiàn)可點(diǎn)擊展開的TextView
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)可點(diǎn)擊展開的TextView,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11

