当前位置:网站首页>10 days to learn how to flutter Day10 flutter play animation and packaging
10 days to learn how to flutter Day10 flutter play animation and packaging
2022-06-30 11:15:00 【Hua Weiyun】
@[toc]( Get along well with Animation and packaging )
Animation
Flutter The animation system in is based on Animation Object's , Different from the previous gesture , It's not a Widget, This is because Animation The object itself and UI Rendering has nothing to do with .Animation Is an abstract class , It's like a timer , It is used to save the interpolation and state of animation , And perform numerical changes .widget Can be in build Function Animation The current value of the object , And you can monitor the state change of the animation .
AnimationController
AnimationController Used to control animation , It contains the start of animation forward()、 stop it stop() 、 Reverse play reverse() Other methods .AnimationController Will be in every frame of the animation , It will generate a new value . By default ,AnimationController Linear generation over a given period of time from 0.0 To 1.0( Default interval ) The number of .
AnimationController controller = AnimationController( duration: const Duration(milliseconds: 2000), // Animation time lowerBound: 10.0, // The interval in which the number is generated upperBound: 20.0, //10.0 - 20.0 vsync: this //TickerProvider Animation driver provider );Ticker
Ticker The function of is to add a screen refresh callback , Every time the screen is refreshed TickerCallback. Use Ticker To drive animation will prevent off screen animation ( The animation UI When not on the current screen , When the screen is locked ) Consume unnecessary resources . because Flutter Will be notified when the screen refreshes Ticker, After locking the screen, the screen will stop refreshing , therefore Ticker It won't trigger again . The simplest way is to SingleTickerProviderStateMixin Add to State The definition of .
import 'package:flutter/material.dart';void main() => runApp(AnimationApp());class AnimationApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: "animation", home: Scaffold( appBar: AppBar( title: Text('animation'), ), body: AnimWidget(), ), ); }}// Animation is stateful class AnimWidget extends StatefulWidget { @override State<StatefulWidget> createState() { return _AnimWidgetState(); }}class _AnimWidgetState extends State<AnimWidget> with SingleTickerProviderStateMixin { AnimationController controller; bool forward = true; @override void initState() { super.initState(); controller = AnimationController( // The length of animation duration: Duration(milliseconds: 2000), lowerBound: 10.0, upperBound: 100.0, // Provide vsync The easiest way , Is to mix directly into SingleTickerProviderStateMixin // If there are more than one AnimationController, Then use TickerProviderStateMixin. vsync: this, ); // Status modification listening controller ..addStatusListener((AnimationStatus status) { debugPrint(" state :$status"); }) ..addListener(() { setState(() => {}); }); debugPrint("controller.value:${controller.value}"); } @override Widget build(BuildContext context) { return Column( children: <Widget>[ Container( width: controller.value, height: controller.value, color: Colors.blue, ), RaisedButton( child: Text(" Play "), onPressed: () { if (forward) { controller.forward(); } else { controller.reverse(); } forward = !forward; }, ), RaisedButton( child: Text(" stop it "), onPressed: () { controller.stop(); }, ) ], ); }}Animation status monitoring : stay forword After completion, the status is completed. stay reverse After completion, the status is dismissed
Tween
By default ,AnimationController The object value is :double type , The scope is 0.0 To 1.0 . If we need different ranges or different data types , You can use Tween To configure the animation to generate values of different ranges or data types . To use Tween object , It needs to be called animate() Method , Then pass in a controller object , At the same time, the values generated in the animation process are determined by Tween Of lerp The method decides .
import 'package:flutter/material.dart';void main() => runApp(AnimationApp());class AnimationApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: "animation", home: Scaffold( appBar: AppBar( title: Text('animation'), ), body: AnimWidget(), ), ); }}// Animation is stateful class AnimWidget extends StatefulWidget { @override State<StatefulWidget> createState() { return _AnimWidgetState(); }}class _AnimWidgetState extends State<AnimWidget> with SingleTickerProviderStateMixin { AnimationController controller; bool forward = true; Tween<Color> tween; @override void initState() { super.initState(); controller = AnimationController( // The length of animation duration: Duration(milliseconds: 2000), // Provide vsync The easiest way , Is direct inheritance SingleTickerProviderStateMixin vsync: this, ); // Use Color tween = ColorTween(begin: Colors.blue, end: Colors.yellow); // Add animation value and modify the monitor tween.animate(controller)..addListener(() => setState(() {})); } @override Widget build(BuildContext context) { return Column( children: <Widget>[ Container( width: 100, height: 100, // Get the current value of the animation color: tween.evaluate(controller), ), RaisedButton( child: Text(" Play "), onPressed: () { if (forward) { controller.forward(); } else { controller.reverse(); } forward = !forward; }, ), RaisedButton( child: Text(" stop it "), onPressed: () { controller.stop(); }, ) ], ); }}Curve
The animation process is linear by default ( uniform ), If you need non-linear , such as : Accelerating or accelerating first and then decelerating, etc .Flutter Through Curve( curve ) To describe the animation process .
import 'package:flutter/material.dart';void main() => runApp(AnimationApp());class AnimationApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: "animation", home: Scaffold( appBar: AppBar( title: Text('animation'), ), body: AnimWidget(), ), ); }}// Animation is stateful class AnimWidget extends StatefulWidget { @override State<StatefulWidget> createState() { return _AnimWidgetState(); }}class _AnimWidgetState extends State<AnimWidget> with SingleTickerProviderStateMixin { AnimationController controller; Animation<double> animation; bool forward = true; @override void initState() { super.initState(); controller = AnimationController( // The length of animation duration: Duration(milliseconds: 2000), // Provide vsync The easiest way , Is direct inheritance SingleTickerProviderStateMixin vsync: this, ); // elastic animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn); // Use Color animation = Tween(begin: 10.0, end: 100.0).animate(animation) ..addListener(() { setState(() => {}); }); } @override Widget build(BuildContext context) { return Column( children: <Widget>[ Container( // There's no need to switch width: animation.value, height: animation.value, // Get the current value of the animation color: Colors.blue, ), RaisedButton( child: Text(" Play "), onPressed: () { if (forward) { controller.forward(); } else { controller.reverse(); } forward = !forward; }, ), RaisedButton( child: Text(" stop it "), onPressed: () { controller.stop(); }, ) ], ); }}AnimatedWidget
Through the above learning, we can feel Animation The object itself and UI Rendering has nothing to do with . And by addListener() and setState() To update UI This step is actually universal , If you add such a sentence in every animation, it is more cumbersome .AnimatedWidget Class encapsulates the call setState() The details of the , Simply put, it is to automatically call setState().
Flutter Many animations have been encapsulated in , For example, yes. widget Zoom , You can use it directly ScaleTransition
import 'package:flutter/material.dart';void main() => runApp(AnimationApp());class AnimationApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: "animation", home: Scaffold( appBar: AppBar( title: Text('animation'), ), body: AnimWidget(), ), ); }}// Animation is stateful class AnimWidget extends StatefulWidget { @override State<StatefulWidget> createState() { return _AnimWidgetState(); }}class _AnimWidgetState extends State<AnimWidget> with SingleTickerProviderStateMixin { AnimationController controller; Animation<double> animation; bool forward = true; @override void initState() { super.initState(); controller = AnimationController( // The length of animation duration: Duration(milliseconds: 2000), // Provide vsync The easiest way , Is direct inheritance SingleTickerProviderStateMixin vsync: this, ); // elastic animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn); // Use Color animation = Tween(begin: 10.0, end: 100.0).animate(animation); } @override Widget build(BuildContext context) { return Column( children: <Widget>[ ScaleTransition( child: Container( width: 100, height: 100, color: Colors.blue, ), scale: controller, ), RaisedButton( child: Text(" Play "), onPressed: () { if (forward) { controller.forward(); } else { controller.reverse(); } forward = !forward; }, ), RaisedButton( child: Text(" stop it "), onPressed: () { controller.stop(); }, ) ], ); }}Hero Animation
Hero The animation is when the route is switched , There is a shared Widget You can switch between old and new routes , Because of shared Widget Location on the old and new routing pages 、 The appearance may vary , Therefore, it will gradually transition during route switching , This will create a Hero Animation .
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter Demo', home: Scaffold( appBar: AppBar( title: Text(" Home page "), ), body: Route1()), ); }}// route Aclass Route1 extends StatelessWidget { @override Widget build(BuildContext context) { return Container( alignment: Alignment.topCenter, child: InkWell( child: Hero( tag: "avatar", // The only mark , Two routing pages before and after Hero Of tag It has to be the same child: CircleAvatar( backgroundImage: AssetImage( "assets/banner.jpeg", ), ), ), onTap: () { Navigator.push(context, MaterialPageRoute(builder: (_) { return Route2(); })); }, ), ); }}class Route2 extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Hero( tag: "avatar", // The only mark , Two routing pages before and after Hero Of tag It has to be the same child: Image.asset("assets/banner.jpeg")), ); }}Combination animation
Sometimes we may need to execute an animation sequence and perform some complex animation .
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter Demo', home: Route(), ); }}class Route extends StatefulWidget { @override State<StatefulWidget> createState() { return RouteState(); }}class RouteState extends State<Route> with SingleTickerProviderStateMixin { Animation<Color> color; Animation<double> width; AnimationController controller; @override void initState() { super.initState(); controller = AnimationController( // The length of animation duration: Duration(milliseconds: 2000), // Provide vsync The easiest way , Is direct inheritance SingleTickerProviderStateMixin vsync: this, ); // Height animation width = Tween<double>( begin: 100.0, end: 300.0, ).animate( CurvedAnimation( parent: controller, curve: Interval( // interval , front 60% The animation time of 1200ms Perform height change 0.0, 0.6, ), ), ); color = ColorTween( begin: Colors.green, end: Colors.red, ).animate( CurvedAnimation( parent: controller, curve: Interval( 0.6, 1.0, // After the height change is completed 800ms Perform color coding ), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(" Home page "), ), body: InkWell( ///1、 There is no need to explicitly add frame listeners , Call again setState() ///2、 Reduce the scope of animation construction , without builder,setState() Will be in the father widget Context call , Cause the father to widget Of build Method is called again , Now it will only lead to animation widget Of build Call again child: AnimatedBuilder( animation: controller, builder: (context, child) { return Container( color: color.value, width: width.value, height: 100.0, ); }), onTap: () { controller.forward().whenCompleteOrCancel(() => controller.reverse()); }, ), ); }}pack
Flutter Fight Release When the package is reused AOT, So in a Flutter When testing, be sure to use Release To test it . Packing command :flutter build apk . Of course, when we need to pack , You also need to configure some content such as signature . Configure these contents as normal Android Engineering makes no difference , It's all in build.gradle In the middle of , It's just Flutter engineering AS Not provided GUI.
stay Flutter engineering android/app Below build.gradle You can modify the package name 、 Version information , There is no need to say much about it . After obtaining the signature file , Copy it to flutter Of android Catalog :

And then in app Of build.gradle Middle configuration :
signingConfigs { release { keyAlias 'enjoy' keyPassword '123456' // Because it is placed in the root directory of the parent , Use rootProject // If you put it here build.gradle My peers , Use it directly file storeFile rootProject.file('enjoy.jks') storePassword '123456' } } buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.release } }The pie chart
https://github.com/google/charts
Stack In the layout fit Properties and Image Of fit similar , Indicates the expansion of the content . The default is
StackFit.looseExpressStackAs big as the content . If set toStackFit.passthroughsaidStackFather Widget The constraints will be passed on to Stack Internal non Positioned The son of Widget. The effect is like... In the codeStackFit.dart

边栏推荐
- Dickinson's soul chooses its companion
- SQL必需掌握的100个重要知识点:联结表
- Lvgl 8.2 picture scaling and rotation
- The precision problem of depth texture in unity shader - stepping pit - BRP pipeline (there is no solution, it is recommended to replace URP)
- 记一次ViewPager + RecyclerView的内存泄漏
- 训练一个图像分类器demo in PyTorch【学习笔记】
- IDEA 又出新神器,一套代码适应多端!
- Kotlin 协程调度切换线程是时候解开谜团了
- SQL必需掌握的100个重要知识点:分组数据
- 基于HAL库的LED驱动库
猜你喜欢

WireGuard简单配置

The two e-commerce bigwigs' lacy news screens represent the return of e-commerce to normal, which will be beneficial to the real economy

China will force a unified charging interface. If Apple does not bow its head, iPhone will be kicked out of the Chinese market

Go language defer

煥發青春的戴爾和蘋果夾擊,兩大老牌PC企業極速衰敗

时间复杂度与空间复杂度
![[understanding of opportunity -34]: fate is within the light cone](/img/3e/9f5630ba382df7f7ce00705445cef8.jpg)
[understanding of opportunity -34]: fate is within the light cone

语音识别-基础(一):简介【语音转文本】

暑假学习记录

Cp2112 teaching example of using USB to IIC communication
随机推荐
ESP32-C3入门教程 基础篇⑪——Non-Volatile Storage (NVS) 非易失性存储参数的读写
记一次ViewPager + RecyclerView的内存泄漏
国产自研系统的用户突破4亿,打破美国企业的垄断,谷歌后悔不迭
在IPhone12的推理延迟仅为1.6 ms!Snap等详析Transformer结构延迟,并用NAS搜出移动设备的高效网络结构...
电商两位大佬花边新闻刷屏,代表电商回归正常,将有利于实体经济
Wechat Emoji is written into the judgment, and every Emoji you send may become evidence in court
Oceanbase installation Yum source configuration error and Solutions
ArrayList and sequence table
SQL必需掌握的100个重要知识点:使用子查询
【小程序实战系列】小程序框架 页面注册 生命周期 介绍
LVGL 8.2 Simple Colorwheel
DataX JSON description
暑假学习记录
单片机 MCU 固件打包脚本软件
LVGL8.2 Simple Checkboxes
Unity Shader - 踩坑 - BRP 管线中的 depth texture 的精度问题(暂无解决方案,推荐换 URP)
蚂蚁金服笔试题:需求文档有什么可以量化的【杭州多测师】【杭州多测师_王sir】...
The number of users of the home-made self-developed system exceeded 400million, breaking the monopoly of American enterprises, and Google repented
China will force a unified charging interface. If Apple does not bow its head, iPhone will be kicked out of the Chinese market
MySQL export SQL script file