当前位置: 首页 > news >正文

Flutter 06 动画

一、动画基本原理以及Flutter动画简介

1、动画原理:

在任何系统的Ul框架中,动画实现的原理都是相同的,即:在一段时间内,快速地多次改变Ul外观;由于人眼会产生视觉暂留,所以最终看到的就是一个“连续”的动画,这和电影的原理是一样的。

我们将UI的一次改变称为一个动画帧,对应一次屏幕刷新,而决定动画流畅度的一个重要指标就是帧率FPS(Frame Per Second),即每秒的动画帧数。

很明显,帧率越高则动画就会越流畅!一般情况下,对于人眼来说,动画帧率超过16FPS,就基本能看了,超过32FPS就会感觉相对平滑,而超过32FPS,大多数人基本上就感受不到差别了。

由于动画的每一帧都是要改变Ul输出,所以在一个时间段内连续的改变Ul输出是比较耗资源的,对设备的软硬件系统要求都较高,所以在Ul系统中,动画的平均帧率是重要的性能指标,而在Flutter中,理想情况下是可以实现60FPS的,这和原生应用能达到的帧率是基本是持平的。

2、FLutter中的动画主要分为:

隐式动画、显式动画、自定义隐式动画、自定义显式动画、Hero动画;

二、隐式动画:

1、说明:

通过几行代码就可以实现隐式动画,由于隐式动画背后的实现原理和繁琐的操作细节都被隐去了,所以叫隐式动画,FLutter中提供的 AnimatedContainer、AnimatedPadding、AnimatedPositioned、AnimatedOpacity、AnimatedDefaultTextStyle、AnimatedSwitcher都属于隐式动画。

隐式动画中可以通过 duration配置动画时长、可以通过 Curve(曲线)来配置动画过程。

2、Curves曲线值:

linear 匀速的;
decelerate 匀减速;
ease 开始加速,后面减速;
easeln 开始慢,后面快;
easeOut 开始快,后面慢;
easelnOut 开始慢,然后加速,最后再减速;

3、AnimatedContainer:

AnimatedContainer的属性和Container属性基本是一样的,当AnimatedContainer属性改变的时候就会触发动画。

代码示例:放大缩小动画

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return const MaterialApp(home: MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: FloatingActionButton(child: const Icon(Icons.animation),onPressed: () {setState(() {flag = !flag;});},),appBar: AppBar(title: const Text("AnimatedContainer Demo"),),body: Center(child: AnimatedContainer(duration: const Duration(milliseconds: 500),// 动画时长500 ms width: flag?100:300,height: flag ? 100 : 300,color: Colors.blue,),),);}
}

4、AnimatedPadding:

代码示例:上下移动动画
import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return const MaterialApp(home: MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: FloatingActionButton(child: const Icon(Icons.animation),onPressed: () {setState(() {flag = !flag;});},),appBar: AppBar(title: const Text("AnimatedContainer Demo"),),body: AnimatedPadding(duration: const Duration(milliseconds: 2000),// 动画时长500 ms curve: Curves.bounceInOut,padding: EdgeInsets.fromLTRB(10, flag ? 10 : 500, 0, 0),child: Container(width: 100,height: 100,color: Colors.red,),),);}
}

5、AnimatedPositioned:

代码示例:对角线移动动画

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return const MaterialApp(home: MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({Key? key}) : super(key: key);@overrideMyHomePageState createState() => MyHomePageState();
}class MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("AnimatedPositioned Demo"),),body: Stack(children: [AnimatedPositioned(curve: Curves.easeInOut,duration: const Duration(seconds: 1),top: flag ? 10 : 500,left: flag ? 10 : 300,child: Container(width: 60,height: 60,color: Colors.blue,),),Align(alignment: const Alignment(0, 0.8),child: ElevatedButton(child: const Text("Transform"),onPressed: () {setState(() {flag = !flag;});},),),],),);}
}

6、AnimatedOpacity:

代码示例:淡入淡出动画

import 'dart:isolate';
import 'dart:math';import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return const MaterialApp(home: MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({Key? key}) : super(key: key);@overrideMyHomePageState createState() => MyHomePageState();
}class MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: FloatingActionButton(onPressed: (){setState(() {flag= !flag;});},child: const Icon(Icons.opacity),),appBar: AppBar(title: const Text("AnimatedPositioned Demo"),),body: Center(child: AnimatedOpacity(curve: Curves.linear,duration: const Duration(seconds: 1),opacity: flag?1:0,child: Container(width: 300,height: 300,color: Colors.blue,),),),);}
}

7、AnimatedDefaultTextStyle:

代码示例:字体放大缩小动画

import 'dart:isolate';
import 'dart:math';import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return const MaterialApp(home: MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({Key? key}) : super(key: key);@override_MyHomePageState createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: FloatingActionButton(onPressed: () {setState(() {flag = !flag;});},child: const Icon(Icons.opacity),),appBar: AppBar(title: const Text("AnimatedPositioned Demo"),),body: Center(child: Container(alignment: Alignment.center,width: 300,height: 300,color: Colors.blue,child: AnimatedDefaultTextStyle(duration: const Duration(seconds: 1),style: TextStyle(fontSize: flag ? 20 : 50,),child: const Text("你好Flutte"),),),),);}
}

8、AnimatedSwitcher 和 transitionBuilder:

AnimatedContainer、AnimatedPadding、AnimatedPositioned、AnimatedOpacity、AnimatedDefaultTextStyle都是在属性改变的时候执行动画,AnimatedSwitcher则是在子元素改变的时候执行动画。

相比上面的动画组件AnimatedSwitcher多了transitionBuilder参数,可以在transitionBuilder中自定义动画

代码示例1、面前显示一个loading动画,加载完毕后显示对于的内容:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return const MaterialApp(home: MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({Key? key}) : super(key: key);@override_MyHomePageState createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: FloatingActionButton(onPressed: () {setState(() {flag = !flag;});},child: const Icon(Icons.opacity),),appBar: AppBar(title: const Text("AnimatedPositioned Demo"),),body: Center(child: Container(alignment: Alignment.center,width: 300,height: 180,color: Colors.yellow,child: AnimatedSwitcher(duration: const Duration(milliseconds: 1000),child: flag? const CircularProgressIndicator(): Image.network("https://pics2.baidu.com/feed/b7003af33a87e9502b64d86f4c2e9544fbf2b45b.jpeg@f_auto?token=8c6557279177a75d44029840f0db0daa&s=C8AA67D91C0090457095310903005057",fit: BoxFit.contain,),),),),);}
}
代码示例2、通过transitionBuilder自定义动画效果:

import 'dart:isolate';
import 'dart:math';import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return const MaterialApp(home: MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({Key? key}) : super(key: key);@override_MyHomePageState createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: FloatingActionButton(onPressed: () {setState(() {flag = !flag;});},child: const Icon(Icons.opacity),),appBar: AppBar(title: const Text("AnimatedPositioned Demo"),),body: Center(child: Container(alignment: Alignment.center,width: 300,height: 180,color: Colors.yellow,child: AnimatedSwitcher(transitionBuilder: ((child, animation) {return ScaleTransition(scale: animation,child: FadeTransition(opacity: animation,child: child,),);}),duration: const Duration(milliseconds: 400),child: flag? const CircularProgressIndicator(): Image.network("https://pics2.baidu.com/feed/b7003af33a87e9502b64d86f4c2e9544fbf2b45b.jpeg@f_auto?token=8c6557279177a75d44029840f0db0daa&s=C8AA67D91C0090457095310903005057",fit: BoxFit.contain,),),),),);}
}
代码示例3、通过transitionBuilder改变子元素执行动画:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return const MaterialApp(home: MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({Key? key}) : super(key: key);@override_MyHomePageState createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: FloatingActionButton(onPressed: () {setState(() {flag = !flag;});},child: const Icon(Icons.opacity),),appBar: AppBar(title: const Text("AnimatedPositioned Demo"),),body: Center(child: Container(alignment: Alignment.center,width: 300,height: 180,color: Colors.yellow,child: AnimatedSwitcher(transitionBuilder: ((child, animation) {return  ScaleTransition(scale: animation,child: FadeTransition(opacity: animation,child:child ,),);}),duration: const Duration(milliseconds: 400),child: Text(key:UniqueKey(),flag?"你好Flutter":"你好世界",style: const TextStyle(fontSize: 30),),),),),);}
}

三、显式动画:

1、说明:

常见的显式动画有RotationTransition、FadeTransition、 ScaleTransition、SlideTransition、Animatedlcon。在显示动画中开发者需要创建一个AnimationController,通过AnimationController控制动画的开始、暂停、重置、跳转、倒播等;

2、RotationTransition旋转 和 AnimationController

1)AnimationController普通用法:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => MyHomePageState();
}class MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {super.initState();// TODO: implement initState_controller = AnimationController(// Vsync 机制可以理解为是显卡与显示器的通信桥梁,显卡在渲染每一帧之前会等待垂直同步信号,// 只有显示器完成了一次刷新时,发出垂直同步信号,显卡才会渲染下一帧,确保刷新率和帧率保// 持同步,以达到供需平衡的效果,防止卡顿现象。vsync:this,duration: const Duration(seconds: 1),);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [RotationTransition(turns: _controller,child: const FlutterLogo(size: 100,),),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.fromLTRB(10, 0, 0, 0), child: Wrap(spacing: 10,alignment: WrapAlignment.center,children: [ElevatedButton(onPressed: () {_controller.forward(); //正序播放一次}, child: const Text("Forward")),ElevatedButton(onPressed: () {_controller.reverse(); //倒序播放一次}, child: const Text("Reverse")),ElevatedButton(onPressed: () {_controller.stop(); //停止播放}, child: const Text("Stop")),ElevatedButton(onPressed: () {_controller.reset(); //重置}, child: const Text("rest")),ElevatedButton(onPressed: () {_controller.repeat(); //重复播放}, child: const Text("repeat"))],),)],),);}
}
2)IowerBound 和 upperBound:

AnimationController用于控制动画,它包含动画的启动forward()、停止 stop()、反向播放reverse()等方法。AnimationController 会在动画的每一帧,就会生成一个新的值。默认情况下,AnimationController 在给定的时间段内线性的生成从 0.0到1.0(默认区间)的数字,我们也可以通过 lowerbound 和 upperBound 来修改 AnimationController 生成数字的区间。

代码示例:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {
// TODO: implement initState_controller = AnimationController(vsync: this,duration: const Duration(seconds: 1),lowerBound: 3, //第三圈转到第五圈upperBound: 5);_controller.addListener(() {print(_controller.value);});}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [RotationTransition(turns: _controller,child: const FlutterLogo(size: 100,),),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),child: Wrap(spacing: 10,alignment: WrapAlignment.center,children: [ElevatedButton(onPressed: () {_controller.forward(); //正序播放一次},child: const Text("Forward")),ElevatedButton(onPressed: () {_controller.reverse(); //倒序播放一次},child: const Text("Reverse")),ElevatedButton(onPressed: () {_controller.stop(); //停止播放},child: const Text("Stop")),ElevatedButton(onPressed: () {_controller.reset(); //重置},child: const Text("rest")),ElevatedButton(onPressed: () {_controller.repeat(); //重复播放},child: const Text("repeat"))],),)],),);}
}

3、FadeTransition 淡入淡出

代码示例:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {_controller = AnimationController(vsync: this,duration: const Duration(seconds: 1),);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [FadeTransition(opacity: _controller,child: const FlutterLogo(size: 80),),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [ElevatedButton(onPressed: () {_controller.forward(); //正序播放一次},child: const Text("Forward")),ElevatedButton(onPressed: () {_controller.reverse(); //倒序播放一次},child: const Text("Reverse")),],),)],),);}
}

4、ScaleTransition缩放 和 Tween

默认情况下,AnimationController对象值的范围是[0.0,1.0]。如果我们需要构建Ul的动画值在不同的范围或不同的数据类型,则可以使用Tween来添加映射以生成不同的范围或数据类型的值

代码示例1、AnimationController控制动画:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}
//示例1:AnimationController控制动画
class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {
// TODO: implement initState_controller = AnimationController(vsync: this,duration: const Duration(seconds: 1),);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [ScaleTransition(scale: _controller,child: const FlutterLogo(size: 80),),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [ElevatedButton(onPressed: () {_controller.forward(); //正序播放一次},child: const Text("Forward")),ElevatedButton(onPressed: () {_controller.reverse(); //倒序播放一次},child: const Text("Reverse")),],),)],),);}
}
代码示例2、AnimationController结合Tween控制动画:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}
//示例2:AnimationController结合Tween控制动画
class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {// TODO: implement initState_controller = AnimationController(vsync: this,duration: const Duration(seconds: 1),);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [ScaleTransition(scale: _controller.drive(Tween(begin: 1, end: 2)),child: const FlutterLogo(size: 80),),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [ElevatedButton(onPressed: () {_controller.forward(); //正序播放一次},child: const Text("Forward")),ElevatedButton(onPressed: () {_controller.reverse(); //倒序播放一次},child: const Text("Reverse")),],),)],),);}
}

5、SlideTransition平移

这是一负责平移的显示动画组件,使用时需要通过position属性传入一个Animated表示位移程度,通常借助Tween实现

代码示例1、_controller.drive驱动动画:左右移动

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {_controller = AnimationController(vsync: this,duration: const Duration(seconds: 1),);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [SlideTransition(position: _controller.drive(Tween(begin: const Offset(0, 0),end: const Offset(1.2, 0),),),child: const FlutterLogo(size: 80),),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [ElevatedButton(onPressed: () {_controller.forward(); //正序播放一次},child: const Text("Forward")),ElevatedButton(onPressed: () {_controller.reverse(); //倒序播放一次},child: const Text("Reverse")),],),),],),);}
}
代码示例2、Tween. animate 驱动动画:左右移动

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {super.initState();_controller = AnimationController(vsync: this,duration: const Duration(seconds: 1),);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [SlideTransition(position: Tween(begin: const Offset(0, 0),end: const Offset(1.2, 0) //表示实际的位置向右移动自身宽度的1.2倍).animate(_controller),child: const FlutterLogo(size: 80),),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [ElevatedButton(onPressed: () {_controller.forward(); //正序播放一次},child: const Text("Forward")),ElevatedButton(onPressed: () {_controller.reverse(); //倒序播放一次},child: const Text("Reverse")),],),)],),);}
}
代码示例3、链式操作修改动画效果:弹性上下移动

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {
// TODO: implement initState_controller = AnimationController(vsync: this,duration: const Duration(seconds: 1),);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [SlideTransition(position:Tween(begin: const Offset(0, -1), end: const Offset(0, 0.8)).chain(CurveTween(curve: Curves.bounceIn)).animate(_controller),child: const FlutterLogo(size: 80),),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [ElevatedButton(onPressed: () {_controller.forward(); //正序播放一次},child: const Text("Forward")),ElevatedButton(onPressed: () {_controller.reverse(); //倒序播放一次},child: const Text("Reverse")),],),)],),);}
}
代码示例4、链式操作修改动动画执行时间:弹性上下移动

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {
// TODO: implement initState_controller = AnimationController(vsync: this,duration: const Duration(seconds: 3),);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [SlideTransition(position:Tween(begin: const Offset(0, -1), end: const Offset(0, 0.8)).chain(CurveTween(curve: Curves.bounceIn)).chain(CurveTween(curve: const Interval(0.8, 1.0))).animate(_controller),child: const FlutterLogo(size: 80),),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [ElevatedButton(onPressed: () {_controller.forward(); //正序播放一次},child: const Text("Forward")),ElevatedButton(onPressed: () {_controller.reverse(); //倒序播放一次},child: const Text("Reverse")),],),)],),);}
}

四、Animatedlcon:

Animatedlcon顾名思义,是一个用于提供动画图标的组件,它的名字虽然是以Animated开头,但是他是一个显式动画组件,需要通过progress属性传入动画控制器,另外需要由lcon属性传入动画图标数据;

代码示例:旋转改变图标

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return const MaterialApp(home: MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {super.initState();_controller =AnimationController(vsync: this, duration: const Duration(seconds: 1));}@overridevoid dispose() {super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: FloatingActionButton(child: const Icon(Icons.add),onPressed: () {_controller.forward();},),appBar: AppBar(title: const Text('Title'),),body: Center(child: AnimatedIcon(//图标效果列表:https://api.flutter.dev/flutter/material/AnimatedIcons-class.htmlicon: AnimatedIcons.menu_close, progress: _controller, size: 40),),);}
}

五、交错动画:

代码示例:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;bool flag = true;@overridevoid initState() {super.initState();_controller = AnimationController(vsync: this,duration: const Duration(seconds: 6),)..repeat(reverse: true);}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),floatingActionButton: FloatingActionButton(child: const Icon(Icons.refresh),onPressed: () {flag ? _controller.forward() : _controller.reverse();flag = !flag;},),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: [SlidingBox(controller: _controller,color: Colors.blue[200],curve: const Interval(0, 0.2),),SlidingBox(controller: _controller,color: Colors.blue[400],curve: const Interval(0.2, 0.4),),SlidingBox(controller: _controller,color: Colors.blue[600],curve: const Interval(0.4, 0.6),),SlidingBox(controller: _controller,color: Colors.blue[800],curve: const Interval(0.6, 0.8),),SlidingBox(controller: _controller,color: Colors.blue[900],curve: const Interval(0.8, 1.0),),],),),);}
}class SlidingBox extends StatelessWidget {final AnimationController controller;final Color? color;final Curve curve;const SlidingBox({super.key,required this.controller,required this.color,required this.curve});@overrideWidget build(BuildContext context) {return SlideTransition(position: Tween(begin: const Offset(0, 0), end: const Offset(0.3, 0)).chain(CurveTween(curve: Curves.bounceInOut)).chain(CurveTween(curve: curve)).animate(controller),child: Container(width: 220,height: 60,color: color,),);}
}

六、自定义动画:

1、TweenAnimationBuilder自定义隐式动画

每当Tween的end发生变化的时候就会触发动画

代码示例1、大小变化:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),floatingActionButton: FloatingActionButton(child: const Icon(Icons.refresh),onPressed: () {setState(() {flag = !flag;});},),body: Center(child: TweenAnimationBuilder(tween: Tween(begin: 100.0, end: flag ? 100.0 : 200.0),duration: const Duration(seconds: 1),builder: ((context, value, child) {return Icon(Icons.star,size: value,);})),),);}
}
代码示例2、透明度变化:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {bool flag = true;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),floatingActionButton: FloatingActionButton(child: const Icon(Icons.refresh),onPressed: () {setState(() {flag = !flag;});},),body: Center(child: TweenAnimationBuilder(tween: Tween(begin: 0.0, end: flag ? 0.0 : 1.0),duration: const Duration(seconds: 1),builder: ((context, value, child) {return Opacity(opacity: value,child: Container(color: Colors.red,width: 200,height: 200,),);})),),);}
}

2、AnimatedBuilder 自定义显式动画

代码示例1、透明度动画:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {super.initState();_controller =AnimationController(vsync: this, duration: const Duration(seconds: 1))..repeat(reverse: true);}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Center(child: AnimatedBuilder(animation: _controller,builder: (BuildContext context, Widget? child) {return Opacity(opacity: _controller.value, //从0到1的变化child: Container(width: 200,height: 200,color: Colors.red,child: const Text("我是一个text组件"),),);},),),);}
}
代码示例2、自定义变化范围:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {super.initState();_controller =AnimationController(vsync: this, duration: const Duration(seconds: 1))..repeat(reverse: true);}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Center(child: AnimatedBuilder(animation: _controller,builder: (BuildContext context, Widget? child) {return Opacity(opacity: Tween(begin: 0.5, end: 1.0).animate(_controller).value, //从0.5到1的变化child: Container(width: 200,height: 200,color: Colors.red,child: const Text("我是一个text组件"),),);},),),);}
}
代码示例3、位置变化:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {super.initState();_controller =AnimationController(vsync: this, duration: const Duration(seconds: 1))..repeat(reverse: true);}@overrideWidget build(BuildContext context) {Animation x = Tween(begin: -100.0, end: 100.0).chain(CurveTween(curve: Curves.easeIn)).chain(CurveTween(curve: const Interval(0.2, 0.8))).animate(_controller);return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Center(child: AnimatedBuilder(animation: _controller,builder: (BuildContext context, Widget? child) {return Container(width: 200,height: 200,color: Colors.red,transform: Matrix4.translationValues(x.value, 0, 0),child: const Text("我是一个text组件"),);},),),);}
}
代码示例4、child优化:

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: const MyHomePage(),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage>with SingleTickerProviderStateMixin {late AnimationController _controller;@overridevoid initState() {super.initState();_controller =AnimationController(vsync: this, duration: const Duration(seconds: 1))..repeat(reverse: true);}@overrideWidget build(BuildContext context) {Animation x = Tween(begin: -100.0, end: 100.0).chain(CurveTween(curve: Curves.easeIn)).chain(CurveTween(curve: const Interval(0.2, 0.4))).animate(_controller);return Scaffold(appBar: AppBar(title: const Text('Title'),),body: Center(child: AnimatedBuilder(animation: _controller,builder: (BuildContext context, Widget? child) {return Container(width: 200,height: 200,color: Colors.red,transform: Matrix4.translationValues(x.value, 0, 0),child: child,);},child: const Text("我是一个text组件"),),),);}
}

七、Hero 动画:

1、Hero动画的使用:

微信朋友圈点击小图片的时候会有一个动画效果到大图预览,这个动画效果就可以使用Hero动画实现。

Hero 指的是可以在路由(页面)之间“飞行”的widget,简单来说 Hero 动画就是在路由切换时,有一个共享的widget 可以在新旧路由间切换。

代码示例:

home.dart:
import 'package:flutter/material.dart';
import '../../res/listData.dart';
import 'hero.dart';
import 'hero2.dart';class HomePage extends StatefulWidget {const HomePage({super.key});@overrideState<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {List<Widget> _getListData() {var tempList = listData2.map((value) {return GestureDetector(onTap: () {Navigator.push(context, MaterialPageRoute(builder: (setting) {// return HeroPage(arguments: {//   "imageUrl": value['imageUrl'],//   "description": value['title'],// });return HeroPage(arguments: {"imageUrl": value['imageUrl'],"description": value['title'],});}));},child: Container(decoration: BoxDecoration(border: Border.all(color: const Color.fromRGBO(233, 233, 233, 0.9), width: 1)),child: Column(children: <Widget>[Hero(tag: value['title'],// child: Image.asset(value['imageUrl'])),child: Image.network(value['imageUrl'],width: 320,height: 120,fit: BoxFit.cover,),),const SizedBox(height: 12),Text(value['title'],textAlign: TextAlign.center,style: const TextStyle(fontSize: 20),)],)),);});return tempList.toList();}@overrideWidget build(BuildContext context) {return GridView.count(crossAxisSpacing: 10.0,//水平子 Widget 之间间距mainAxisSpacing: 10.0,//垂直子 Widget 之间间距padding: const EdgeInsets.all(10),crossAxisCount: 2,//一行的 Widget 数量// childAspectRatio:0.7,// 宽度和高度的比例children: _getListData(),);}
}
hero.dart:
import 'package:flutter/material.dart';class HeroPage extends StatefulWidget {final Map arguments;const HeroPage({super.key, required this.arguments});@overrideState<HeroPage> createState() => _HeroPageState();
}class _HeroPageState extends State<HeroPage> {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("详情页面"),),body: ListView(children: [Hero(tag: widget.arguments["imageUrl"],child: Image.network(widget.arguments["imageUrl"])),const SizedBox(height: 20),Padding(padding: const EdgeInsets.all(5),child: Text(widget.arguments["description"],style: const TextStyle(fontSize: 22)),)],),);}
}

2、Hero +photo_view 实现微信朋友圈图片预览:

photo_view预览图片: 

 

代码示例:

home.dart:
import 'package:flutter/material.dart';
import '../../res/listData.dart';
import 'hero.dart';
import 'hero2.dart';class HomePage extends StatefulWidget {const HomePage({super.key});@overrideState<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {List<Widget> _getListData() {var tempList = listData2.map((value) {return GestureDetector(onTap: () {Navigator.push(context, MaterialPageRoute(builder: (setting) {// return HeroPage(arguments: {//   "imageUrl": value['imageUrl'],//   "description": value['title'],// });return HeroPage2(arguments: {"imageUrl": value['imageUrl'],"description": value['title'],});}));},child: Container(decoration: BoxDecoration(border: Border.all(color: const Color.fromRGBO(233, 233, 233, 0.9), width: 1)),child: Column(children: <Widget>[Hero(tag: value['title'],// child: Image.asset(value['imageUrl'])),child: Image.network(value['imageUrl'],width: 320,height: 120,fit: BoxFit.cover,),),const SizedBox(height: 12),Text(value['title'],textAlign: TextAlign.center,style: const TextStyle(fontSize: 20),)],)),);});return tempList.toList();}@overrideWidget build(BuildContext context) {return GridView.count(crossAxisSpacing: 10.0,//水平子 Widget 之间间距mainAxisSpacing: 10.0,//垂直子 Widget 之间间距padding: const EdgeInsets.all(10),crossAxisCount: 2,//一行的 Widget 数量// childAspectRatio:0.7,// 宽度和高度的比例children: _getListData(),);}
}
hero2.dart:
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';class HeroPage2 extends StatefulWidget {final Map arguments;const HeroPage2({super.key, required this.arguments});@overrideState<HeroPage2> createState() => _HeroPageState();
}class _HeroPageState extends State<HeroPage2> {@overrideWidget build(BuildContext context) {return GestureDetector(onTap: () {Navigator.pop(context);},child: Hero(tag: widget.arguments["imageUrl"],child: Scaffold(backgroundColor: Colors.black,body: Center(child: AspectRatio(aspectRatio: 16 / 9,child: PhotoView(imageProvider: NetworkImage(widget.arguments["imageUrl"]),),),),),),);}
}

相关文章:

Flutter 06 动画

一、动画基本原理以及Flutter动画简介 1、动画原理&#xff1a; 在任何系统的Ul框架中&#xff0c;动画实现的原理都是相同的&#xff0c;即&#xff1a;在一段时间内&#xff0c;快速地多次改变Ul外观&#xff1b;由于人眼会产生视觉暂留&#xff0c;所以最终看到的就是一个…...

优化改进YOLOv5算法之添加MS-Block模块,有效提升目标检测效果(超详细)

目录 前言 1 MS-Block原理 1.1 Multi-Scale Building Block Design 1.2 Heterogeneous Kernel Selection Protocol 2 YOLOv5算法中加入MS-Block...

【论文阅读】Iterative Poisson Surface Reconstruction (iPSR) for Unoriented Points

文章目录 声明作者列表核心思想归纳算法流程机器翻译声明 本帖更新中如有问题,望批评指正!如果有人觉得帖子质量差,希望在评论中给出建议,谢谢!作者列表 FEI HOU(侯飞)、CHIYU WANG、WENCHENG WANG:中国科学院大学 HONG QIN CHEN QIAN、YING HE 核心思想归纳 当一条从…...

通过akshare获取股票分钟数据

参考:https://blog.csdn.net/qnloft/article/details/131218295 import akshare as ak 个股的 df ak.stock_zh_a_hist_min_em(symbol“000001”, start_date“2023-11-03 09:30:00”, end_date“2023-11-03 15:00:00”, period‘1’, adjust‘’) print(df) date_info df[‘…...

【论文阅读笔记】Traj-MAE: Masked Autoencoders for Trajectory Prediction

Abstract 通过预测可能的危险&#xff0c;轨迹预测一直是构建可靠的自动驾驶系统的关键任务。一个关键问题是在不发生碰撞的情况下生成一致的轨迹预测。为了克服这一挑战&#xff0c;我们提出了一种有效的用于轨迹预测的掩蔽自编码器(Traj-MAE)&#xff0c;它能更好地代表驾驶…...

MySQL - Zero date value prohibited

问题: timestamp字段报Caused by: com.mysql.cj.exceptions.DataReadException: Zero date value prohibited 原因: timestamp字段存入了0值, 超出了最小值1900-01-01 00:00:00, 转Java对象的时候报错 解决: 1.修复或删除原数据 2. mysqlurl 中添加zeroDateTimeBehaviorconve…...

设计模式——迭代器模式(Iterator Pattern)+ Spring相关源码

文章目录 一、迭代器模式二、例子2.1 菜鸟例子2.1.1 定义迭代器接口2.1.2 定义迭代对象接口——用于返回一个迭代器2.1.3 实现 迭代对象 和 迭代器2.1.4 使用 2.2 JDK源码——ArrayList2.3 Spring源码——DefaultListableBeanFactory 三、其他设计模式 一、迭代器模式 类型&am…...

【word技巧】ABCD选项如何对齐?

使用word文件制作试卷&#xff0c;如何将ABCD选项全部设置对齐&#xff1f;除了一直按空格或者Tab键以外&#xff0c;还有其他方法吗&#xff1f;今天分享如何将ABCD选项对齐。 首先&#xff0c;我们打开【替换和查找】&#xff0c;在查找内容输入空格&#xff0c;然后点击全部…...

如何在uni-app小程序端实现长按复制功能

在开发小程序应用中&#xff0c;常常需要使用到长按复制功能。本文将介绍如何在uni-app小程序端实现长按复制功能。 uni-app是一个跨平台的开发框架&#xff0c;可以基于vue.js语法开发小程序、H5、APP等多个平台的应用。uni-app提供了一些内置组件和API&#xff0c;可以方便地…...

基于springboot实现在线考试平台项目【项目源码+论文说明】计算机毕业设计

基于springboot实现在线考试演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把在线考试管理与现在网络相结合&#xff0c;利用java技术建设在线考试系统&#xff0c;实现在线考试的信息化。则对于进一步提高在线考试管理发展&#xff0c;丰富在线考试管理经验能起到不少…...

【移远QuecPython】EC800M物联网开发板的内置GNSS定位获取(北斗、GPS和GNSS)

【移远QuecPython】EC800M物联网开发板的内置GNSS定位获取&#xff08;北斗、GPS和GNSS&#xff09; 测试视频&#xff08;其中的恶性BUG会在下一篇文章阐述&#xff09;&#xff1a; 【移远QuecPython】EC800M物联网开发板的内置GNSS定位的恶性BUG&#xff08;目前没有完全的…...

软件设计师2016下半年下午——KMP算法和装饰设计模式

下面是提供的代码的逐行注释&#xff0c;以及对next数组在KMP算法中的作用的解释&#xff1a; #include <iostream> #include <vector> using namespace std;void buildNextArray(const char* pattern, vector<int>& next) {int m strlen(pattern); …...

Android Studio run main()方法报错

在studio中想要测试某个功能直接执行main()方法报错如下&#xff1a; * What went wrong: A problem occurred configuring project :app. > Could not create task :app: **** .main().> SourceSet with name main not found.解决方案&#xff1a; 执行run ** main() w…...

CM3D2 汉化杂记

老物难找资源&#xff0c;于是尝试自己汉化&#xff0c;皆源于有一个好的汉化插件。 资源&#xff1a;LMMT 工具&#xff1a;CM3D2.SubtitleDumper.exe&#xff0c;有道翻译(可以翻译文档)&#xff0c;Libreoffice(文档、表格) cmd&#xff08;资源管理器的结果可以拖进去&…...

分类预测 | Matlab实现SMA-KELM黏菌优化算法优化核极限学习机分类预测

分类预测 | Matlab实现SMA-KELM黏菌优化算法优化核极限学习机分类预测 目录 分类预测 | Matlab实现SMA-KELM黏菌优化算法优化核极限学习机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现SMA-KELM黏菌优化算法优化核极限学习机分类预测(完整源码和数…...

linux的环境安装以及部署前后端分离后台接口

⭐⭐ linux专栏&#xff1a;linux专栏 ⭐⭐ 个人主页&#xff1a;个人主页 目录 一.linux安装环境 1.1 jdk和tomcat的安装配置 1.1.1 解压jdk和tomcat的安装包 解压jdk安装包 解压tomcat安装包 1.2 jdk环境变量配置 1.3 tomcat启动 1.4 MySQL的安装 二.部署前后端分离…...

解决mysql数据库root用户看不到库

第一种方式&#xff1a; 1.首先停止MySQL服务&#xff1a;service mysqld stop 2.加参数启动mysql&#xff1a;/usr/bin/mysqld_safe --skip-grant-tables & 然后就可以无任何限制的访问mysql了 3.root用户登陆系统&#xff1a;mysql -u root -p mysql 4.切换数据库&#…...

【LeetCode】117. 填充每个节点的下一个右侧节点指针 II

117. 填充每个节点的下一个右侧节点指针 II 难度&#xff1a;中等 题目 给定一个二叉树&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; }填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点&#xff0c…...

《研发效能(DevOps)工程师》课程简介(三)丨IDCF

在研发效能领域中&#xff0c;【开发与交付】的学习重点在于掌握高效的开发工具和框架&#xff0c;了解敏捷开发方法&#xff0c;掌握持续集成与持续交付技术&#xff0c;以及如何保证应用程序的安全性和合规性等方面。 由国家工业和信息化部教育与考试中心颁发的职业技术证书…...

主动激活木马加密流量分析

概述 在网络攻击中&#xff0c;木马病毒通常会使用监听某个端口的方式&#xff0c;或者直接连接C2地址、域名的方式来建立通信&#xff0c;完成命令与控制。而APT攻击中&#xff0c;攻击者为了更高级的潜伏隐蔽需求&#xff0c;其部署的木马或后门&#xff0c;会采用对网卡流量…...

关于单片机CPU如何控制相关引脚

目录 1、相关的单片机结构 2、通过LED的实例解释 1、相关的单片机结构 在寄存器中每一块都有一根导线与引脚对应&#xff0c;通过cpu改变寄存器内的数据&#xff08;0或1&#xff09;&#xff0c;通过驱动器来控制对于的引脚。 2、通过LED的实例解释 如图所示&#xff0c;芯片…...

[概述] 获取点云数据的仪器

这里所说的获取点云的仪器指的是可以获取场景中物体距离信息的相关设备&#xff0c;下面分别从测距原理以及适用场景来进行介绍。 一、三角测距法 三角测距原理 就是利用三角形的几何关系来测量物体的距离。想象一下&#xff0c;你站在一个地方&#xff0c;你的朋友站在另一…...

路由器基础(八):策略路由配置

在实际网络应用中&#xff0c;策略路由也是一种重要的技术手段。尽管 在考试并不注重策略路由&#xff0c;但是实际上应用较多&#xff0c;建议考生除了掌握基本的静态路由协议IP route-static, 动态路由协议RIP 、OSPF的基础配置外&#xff0c;还要掌握如何配置策略路由。…...

Java 零碎知识点

目录 [多线程]创建多线程的三种方式 [网络编程]一、重点概念1、TCP/IP网络模型2、IP 对象3、端口号4、协议UDP(User Datagram Protocol)TCP(Transmission Control Protocol) 二、UDP 通信三、TCP 通信 [前端][Vue]一、Vue3项目创建响应式函数父子通信父传子子传父 跨层组件通信…...

多模态论文阅读之BLIP

BLIP泛读 TitleMotivationContributionModel Title BLIP: Bootstrapping Language-Image Pre-training for Unified Vision-Language Understanding and Generation Motivation 模型角度&#xff1a;clip albef等要么采用encoder-base model 要么采用encoder-decoder model.…...

OpenCV实战——OpenCV.js介绍

OpenCV实战——OpenCV.js介绍 0. 前言1. OpenCV.js 简介2. 网页编写3. 调用 OpenCV.js 库4. 完整代码相关链接 0. 前言 本节介绍如何使用 JavaScript 通过 OpenCV 开发计算机视觉算法。在 OpenCV.js 之前&#xff0c;如果想要在 Web 上执行一些计算机视觉任务&#xff0c;必须…...

qt5工程打包成可执行exe程序

一、编译生成.exe 1.1、在release模式下编译生成.exe 1.2、建一个空白文件夹package&#xff0c;再将在release模式下生成的.exe文件复制到新建的文件夹中package。 1.3、打开QT5的命令行 1.4、用命令行进入新建文件夹package&#xff0c;使用windeployqt对生成的exe文件进行动…...

Qt之基于QCustomPlot绘制直方图(Histogram),叠加正态分布曲线

一.效果 二.原理 1.正态分布 高斯分布(Gaussian distribution),又名正态分布(Normal distribution),也称"常态分布",也就是说,在正常的状态下,一般的事物,都会符合这样的分布规律。 比如人的身高为一个随机变量,特别高的人比较少,特别矮的也很少,大部分都…...

232.用栈实现队列

原题链接&#xff1a;232.用栈实现队列 思路 主要是要注意栈和队列的数据结构的区别&#xff0c;一个是后进先出&#xff0c; 一个是先进先出 如果要用栈模拟队列的先进先出&#xff0c;那就得使用另一个辅助空间来存储栈的栈顶元素&#xff0c;然后把栈最底部的元素弹出&…...

C51--项目--感应开关盖垃圾桶

1、项目概述 功能描述&#xff1a; 检测靠近时&#xff0c;垃圾桶自动开盖并伴随滴一声&#xff0c;2s后关盖。 发生震动时&#xff0c;垃圾桶自动开盖并伴随滴一声&#xff0c;2s后关盖。 按下按键时&#xff0c;垃圾桶自动开盖并伴随滴一声&#xff0c;2s后关盖。 硬件说明…...