本篇文章已授權微信公眾號 YYGeeker
獨家釋出轉載請標明出處
AnimatedContainer
1、簡介
AnimatedContainer
表示一個動畫容器,只要更改容器的值,就能表現出對應的動畫效果
2、建構函式
AnimatedContainer({
Key key,
this.alignment,
this.padding,
Color color,
Decoration decoration,
this.foregroundDecoration,
double width,
double height,
BoxConstraints constraints,
this.margin,
this.transform,
this.child,
Curve curve = Curves.linear,
@required Duration duration,
})
複製程式碼
- alignment
alignment
表示子元素child相對於容器的對其方式- child在
AnimatedContainer
中預設位於居中位置 - 用座標表示
child
當前的aligament方式,則為(0,0) - 用座標表示
AnimatedContainer
的四個頂點,則為(-1,-1)(-1,1)(1,-1)(1,1) - 通過
AlignmentDirectional
控制child在X、Y軸的偏移,
- padding:可以對子元素child進行內邊距位置偏移
- color:容器的背景色,通過
decoration
也能設定背景色,兩者不可共存 - decoration:容器的邊框修飾,通過
color
也能設定背景色,兩者不可共存 - foregroundDecoration:容器的前景邊框修飾,在這裡做邊框修飾,則會擋住
decoration
或color
的顏色 - width:容器的寬度
- height:容器的高度
- constraints:容器的大小約束,可以指定最小寬高和最大寬高,整個容器遵循這個約束
- margin:容器的外邊距
- transform:容器的Matrix變換,可以進行矩陣的旋轉,縮放,運算等操作
- child:子元素在容器中的位置預設是居中顯示
- curve:容器的動畫插值器
- duration:容器的動畫時長
3、例子
通過定時器改變容器的大小,邊框,邊距等屬性,讓容器動起來
var time = 0;
var _color = Colors.red[200];
var _borderColor = Colors.transparent;
var _width = 200.0;
var _height = 200.0;
var _borderWidth = 0.0;
var _scaleX = 1.0;
var _scaleY = 1.0;
var _rotate = 0.0;
var _padding = 0.0;
var _margin = 0.0;
var _alignmentY = 0.0;
class WeWidgetState extends State<WeWidget> {
WeWidgetState() {
Timer.periodic(Duration(milliseconds: 1000), (timer) {
setState(() {
switch (time % 10) {
case 0:
_width = 300;
_height = 100;
break;
case 1:
_width = 100;
_height = 300;
_borderWidth = 4.0;
_borderColor = Colors.brown[200];
break;
case 2:
_borderWidth = 8.0;
_borderColor = Colors.pink[200];
_color = Colors.blue[200];
break;
case 3:
_width = 300;
_height = 300;
_color = Colors.deepPurple[200];
break;
case 4:
_scaleX = 0.2;
_scaleY = 0.2;
break;
case 5:
_scaleX = 0.5;
_scaleY = 0.5;
_rotate = math.pi / 6;
break;
case 6:
_scaleX = 1.0;
_scaleY = 1.0;
_rotate = 0.0;
_padding = 200.0;
break;
case 7:
_padding = 0.0;
break;
case 8:
_margin = 80.0;
_alignmentY = 0.5;
break;
case 9:
_margin = 0.0;
_alignmentY = 0.0;
break;
}
time++;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("day6"),
),
resizeToAvoidBottomPadding: false,
body: _buildColumn(),
);
}
Widget _buildColumn() {
return Column(
children: <Widget>[
AnimatedContainer(
transform: Matrix4.identity().scaled(_scaleX, _scaleY)
..rotateZ(_rotate),
alignment: AlignmentDirectional(0.0, _alignmentY),
constraints: BoxConstraints(
minWidth: 0.0,
minHeight: 0.0,
maxWidth: 500.0,
maxHeight: 500.0,
),
margin: EdgeInsets.only(left: _margin),
padding: EdgeInsets.only(left: _padding),
width: _width,
height: _height,
duration: Duration(milliseconds: 1000),
curve: Curves.fastOutSlowIn,
child: Icon(
Icons.android,
color: Colors.lightGreenAccent,
size: 40,
),
foregroundDecoration: BoxDecoration(
border: Border.all(
color: _borderColor,
width: _borderWidth,
),
),
//color 和 decoration兩者不可共存
//color: _color,
decoration: BoxDecoration(
color: _color,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: _color,
offset: Offset(5.0, 5.0),
blurRadius: 6.0,
)
],
),
),
],
);
}
}
複製程式碼
AnimatedCrossFade
1、簡介
AnimatedCrossFade
存放著兩個動畫的容器,只要切換動畫的狀態,就能表現出對應的動畫效果AnimatedCrossFade
本質就是一個Stack分別存放有兩個元件和兩個動畫
2、建構函式
const AnimatedCrossFade({
Key key,
@required this.firstChild,
@required this.secondChild,
this.firstCurve = Curves.linear,
this.secondCurve = Curves.linear,
this.sizeCurve = Curves.linear,
this.alignment = Alignment.topCenter,
@required this.crossFadeState,
@required this.duration,
this.layoutBuilder = defaultLayoutBuilder,
})
複製程式碼
- firstChild:第一個動畫元素的控制元件
- secondChild:第二個動畫元素的控制元件
- firstCurve:第一個動畫元素的插值器
- secondCurve:第二個動畫元素的插值器
- sizeCurve:動畫切換時候的尺寸變化插值器
- alignment:動畫在切換到第二個狀態的時候,當前alignment的引數會應用在第二個動畫元素中
- crossFadeState:動畫當前的狀態,當狀態變化時,動畫也會隨之切換到對應的元素上
- duration:動畫時長
- layoutBuilder:動畫布局的構造器,可以構建兩個動畫元素之間的佈局關係
3、例子
通過定時器更改變數的值,讓控制元件切換佈局,從而開啟動畫
var time = 0;
var _first = true;
class WeWidgetState extends State<WeWidget> {
WeWidgetState() {
Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
switch (time % 4) {
case 0:
_first = false;
break;
case 2:
_first = true;
break;
}
time++;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("day7"),
),
body: _buildColumn(),
);
}
Widget _buildColumn() {
return Column(
children: <Widget>[
AnimatedCrossFade(
//layoutBuilder: ,
alignment: AlignmentDirectional(0.0, 1.0),
duration: Duration(seconds: 1),
firstCurve: Curves.fastOutSlowIn,
secondCurve: Curves.fastOutSlowIn,
sizeCurve: Curves.fastOutSlowIn,
firstChild: FlutterLogo(
style: FlutterLogoStyle.horizontal,
size: 100.0,
),
secondChild: FlutterLogo(
style: FlutterLogoStyle.stacked,
size: 200.0,
),
crossFadeState:
_first ? CrossFadeState.showFirst : CrossFadeState.showSecond,
),
],
);
}
}
複製程式碼
Hero
1、簡介
- Hero控制元件屬於Android裡的共享元素動畫,它可以在不同的頁面跳轉時,複用同一個控制元件,且帶有動畫效果
2、建構函式
const Hero({
Key key,
@required this.tag,
this.createRectTween,
this.flightShuttleBuilder,
this.placeholderBuilder,
this.transitionOnUserGestures = false,
@required this.child,
})
複製程式碼
- tag:共享元素的Tag
- createRectTween:定義目標從起點到終點的邊界變化動畫
- flightShuttleBuilder:自定義跳轉時候運動軌跡動畫的控制元件
- placeholderBuilder:自定義跳轉時候的佔位符
- transitionOnUserGestures:支援iOS的返回滑動手勢
- child:子控制元件
3、例子
設定點選加號圖示跳轉到太陽圖示的頁面,在跳轉的時候用相機快門圖示做軌跡運動,同時會有載入佔位符
class WeWidgetState extends State<WeWidget> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("day8"),
),
body: GestureDetector(
child: _buildColumn(),
onTap: () {
_pushToNewPage();
},
),
);
}
Widget _buildColumn() {
return Hero(
tag: "mmm",
transitionOnUserGestures: true,
placeholderBuilder: (context, size, widget) {
return CircularProgressIndicator();
},
flightShuttleBuilder: (flightContext, animation, flightDirection,
fromHeroContext, toHeroContext) {
return Icon(
Icons.camera,
size: 70.0,
);
},
child: Icon(
Icons.add,
size: 70.0,
),
);
}
void _pushToNewPage() {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) {
return Scaffold(
appBar: AppBar(
title: Text('Hero'),
),
body: Center(
child: Hero(
tag: "mmm",
child: Icon(
Icons.wb_sunny,
size: 70.0,
),
),
));
}),
);
}
}
複製程式碼
AnimatedBuilder
1、簡介
AnimatedBuilder
表示一個動畫的構造器,可以通過控制器去控制動畫值改變,從而控制動畫
2、建構函式
AnimatedBuilder({
Key key,
Listenable animation,
this.builder,
this.child,
})
複製程式碼
- animation:表示由外傳遞進來的動畫屬性值的變化
- builder:動畫的控制器
- child:子控制元件
3、例子
我們可以將常用屬性包裝成一個控制元件
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
child: this.child,
animation: animation,
builder: (BuildContext context, Widget child) {
return Container(
height: animation.value,
width: animation.value,
child: child,
);
},
),
);
}
}
複製程式碼
動畫屬性值的變化需要AnimationController
來控制,通過CurvedAnimation
設定其插值器,通過Tween
設定其值的變化範圍
class WeWidgetState extends State<WeWidget>
with SingleTickerProviderStateMixin {
//嘗試擴充套件或實現num時,除int或double之外的任何型別都是編譯時錯誤
Animation<num> _animation;
AnimationController _controller;
Animation _curve;
@override
void initState() {
super.initState();
//動畫控制器
_controller = AnimationController(
duration: const Duration(milliseconds: 3000),
vsync: this,
);
//動畫插值器
_curve = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
//動畫變化範圍
_animation = Tween(begin: 0.0, end: 300.0).animate(_curve);
//啟動動畫
_controller.forward();
}
}
複製程式碼
通過addStatusListener
監聽動畫狀態的變化和通過addListener
監聽動畫值的變化
class WeWidgetState extends State<WeWidget>
with SingleTickerProviderStateMixin {
//嘗試擴充套件或實現num時,除int或double之外的任何型別都是編譯時錯誤
Animation<num> _animation;
AnimationController _controller;
Animation _curve;
double _animationValue;
AnimationStatus _state;
@override
void initState() {
super.initState();
//動畫控制器
_controller = AnimationController(
duration: const Duration(milliseconds: 3000),
vsync: this,
);
//動畫插值器
_curve = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
//動畫變化範圍
_animation = Tween(begin: 0.0, end: 300.0).animate(_curve)
..addListener(() {
setState(() {
//記錄變化的值
_animationValue = _animation.value;
});
})
..addStatusListener((AnimationStatus state) {
//如果動畫已完成,就反轉動畫
if (state == AnimationStatus.completed) {
_controller.reverse();
} else if (state == AnimationStatus.dismissed) {
//如果動畫已經消失,則開始動畫
_controller.forward();
}
setState(() {
_state = state;
});
});
//啟動動畫
_controller.forward();
}
}
複製程式碼
原始碼
class WeWidgetState extends State<WeWidget>
with SingleTickerProviderStateMixin {
//嘗試擴充套件或實現num時,除int或double之外的任何型別都是編譯時錯誤
Animation<num> _animation;
AnimationController _controller;
Animation _curve;
double _animationValue;
AnimationStatus _state;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 3000),
vsync: this,
);
_curve = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn);
_animation = Tween(begin: 0.0, end: 300.0).animate(_curve)
..addListener(() {
setState(() {
_animationValue = _animation.value;
});
})
..addStatusListener((AnimationStatus state) {
if (state == AnimationStatus.completed) {
_controller.reverse();
} else if (state == AnimationStatus.dismissed) {
_controller.forward();
}
setState(() {
_state = state;
});
});
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("day10"),
),
body: _buildColumn(),
);
}
Widget _buildColumn() {
return Column(
children: <Widget>[
AnimatorTransition(
child: FlutterLogo(
style: FlutterLogoStyle.horizontal,
),
animation: _animation,
),
Text("動畫值:" + _animationValue.toString()),
Text("動畫狀態:" + _state.toString()),
],
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
child: this.child,
animation: animation,
builder: (BuildContext context, Widget child) {
return Container(
height: animation.value,
width: animation.value,
child: child,
);
},
),
);
}
}
複製程式碼
DecoratedBoxTransition
1、簡介
DecoratedBoxTransition
表示一個邊框動畫,可以通過控制器去控制動畫邊框值的改變,從而控制動畫邊框
2、建構函式
DecoratedBoxTransition({
Key key,
this.decoration,
this.position,
this.child,
})
複製程式碼
- decoration:動畫屬性值的變化,注意這裡的型別是
Animation<Decoration>
- position:動畫的控制器
- child:子控制元件
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<Decoration> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: DecoratedBoxTransition(
position: DecorationPosition.background,
decoration: animation,
child: Container(
child: this.child,
),
),
);
}
}
複製程式碼
FadeTransition
1、簡介
FadeTransition
表示一個透明度動畫,可以通過控制器去控制動畫透明度值的改變,從而控制動畫的透明度
2、建構函式
FadeTransition({
Key key,
this.opacity,
this.alwaysIncludeSemantics,
Widget child,
})
複製程式碼
- opacity:動畫屬性值的變化,注意這裡的型別是
Animation<num>
- alwaysIncludeSemantics:是否包含子語義而不管不透明度
- child:子控制元件
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: FadeTransition(
//是否包含子語義而不管不透明度
alwaysIncludeSemantics: false,
opacity: animation,
child: this.child,
),
);
}
}
複製程式碼
PositionedTransition
1、簡介
PositionedTransition
表示一個矩形位置的動畫,可以通過控制器去控制動畫矩形值的改變,從而控制動畫的矩形位置
2、建構函式
PositionedTransition({
Key key,
this.rect,
Widget child,
})
複製程式碼
- rect:動畫屬性值的變化,注意這裡的型別是
Animation<RelativeRect>
- child:子控制元件
3、例子
這裡需要注意的是PositionedTransition的父控制元件必須是Stack
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<RelativeRect> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
//絕對定位的動畫實現, 需要Stack包裹
return Stack(
children: <Widget>[
PositionedTransition(
rect: animation,
child: this.child,
),
],
);
}
}
複製程式碼
RotationTransition
1、簡介
RotationTransition
表示一個旋轉動畫,可以通過控制器去控制動畫旋轉值的改變,從而控制動畫的旋轉
2、建構函式
RotationTransition({
Key key,
this.turns,
this.alignment,
Widget child,
})
複製程式碼
- turns:動畫旋轉值的變化,注意這裡的型別是
Animation<num>
- alignment:旋轉的錨定座標
- child:子控制元件
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: RotationTransition(
//旋轉的錨定座標
alignment: Alignment.center,
turns: animation,
child: this.child,
),
);
}
}
複製程式碼
ScaleTransition
1、簡介
ScaleTransition
表示一個縮放動畫,可以通過控制器去控制動畫縮放值的改變,從而控制動畫的縮放
2、建構函式
ScaleTransition({
Key key,
this.scale,
this.alignment,
Widget child,
})
複製程式碼
- scale:動畫屬性值的變化,注意這裡的型別是
Animation<num>
- alignment:旋轉的錨定座標
- child:子控制元件
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: ScaleTransition(
//縮放的錨定座標
alignment: Alignment.topLeft,
scale: animation,
child: this.child,
),
);
}
}
複製程式碼
SizeTransition
1、簡介
SizeTransition
表示一個尺寸動畫,可以通過控制器去控制動畫尺寸值的改變,從而控制動畫的尺寸
2、建構函式
SizeTransition({
Key key,
this.sizeFactor,
this.axis,
this.axisAlignment,
Widget child,
})
複製程式碼
- sizeFactor:動畫屬性值的變化,注意這裡的型別是
Animation<num>
- axis:表示動畫出現的方式
- Axis.vertical:垂直方向
- Axis.horizontal:橫軸方向
- axisAlignment:表示動畫出現的原始位置偏移量,如果是在垂直方向指的是y,如果是橫軸方向指的是x
- child:子控制元件
3、例子
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<num> animation;
final Axis axis;
AnimatorTransition({this.child, this.animation, this.axis = Axis.vertical});
@override
Widget build(BuildContext context) {
return Center(
child: SizeTransition(
axisAlignment: 2.0,
axis: axis,
sizeFactor: animation,
child: this.child,
),
);
}
}
複製程式碼
SlideTransition
1、簡介
SlideTransition
表示一個平移動畫,可以通過控制器去控制動畫尺寸值的改變,從而控制動畫的平移位置
2、建構函式
SlideTransition({
Key key,
this.position,
this.transformHitTests,
this.textDirection,
Widget child,
})
複製程式碼
- position:動畫屬性值的變化,注意這裡的型別是
Animation<Offset>
- transformHitTests:表示點選事件是否落在動畫後的控制元件上
- textDirection:表示動畫執行的位置關係
- TextDirection.rtl:左到右
- TextDirection.ltr:右到左
- child:子控制元件
class AnimatorTransition extends StatelessWidget {
final Widget child;
final Animation<Offset> animation;
AnimatorTransition({this.child, this.animation});
@override
Widget build(BuildContext context) {
return Center(
child: SlideTransition(
transformHitTests: true,
textDirection: TextDirection.rtl,
position: animation,
child: this.child,
),
);
}
}
複製程式碼
作者
Hensen_ |