分页下标动画源码
2019-07-04 本文已影响0人
twj小鱼儿
直接引用 YJPvAnimationWidget()作为控件即可看效果。
import 'package:flutter/material.dart';
enum YJPvAnimationDirection {
left,
right,
}
class YJPvAnimationSharedModel {
String action; //动画动作
YJPvAnimationDirection direction;
YJPvAnimationSharedModel({this.action = 'wait', this.direction = YJPvAnimationDirection.right});
}
class YJPvAnimationSharedContext extends InheritedWidget{
YJPvAnimationSharedModel model;
YJPvAnimationSharedContext({
Key key,
@required this.model,
@required Widget child,YJPvAnimationSharedModel
}) : super(key: key, child: child);
static YJPvAnimationSharedContext of(BuildContext context){
return context.inheritFromWidgetOfExactType(YJPvAnimationSharedContext);
}
@override
bool updateShouldNotify(YJPvAnimationSharedContext oldWidget) {
// TODO: implement updateShouldNotify
print('updateShouldNotify');
return true;
}
}
class YJPvAnimationWidget extends StatefulWidget {
@override
_YJPvAnimationWidgetState createState() => _YJPvAnimationWidgetState();
}
class _YJPvAnimationWidgetState extends State<YJPvAnimationWidget> {
YJPvAnimationSharedModel model;
@override
void initState() {
// TODO: implement initState
model = new YJPvAnimationSharedModel();
super.initState();
}
@override
Widget build(BuildContext context) {
return new YJPvAnimationSharedContext(
model: model,
child: Container(
color: Colors.grey,
height: 60,
width: double.infinity,
child: Stack(
children: <Widget>[
Positioned(
child: Container(
color:Colors.yellow,
alignment: Alignment.center,
width: 100,
height: 10,
child: YJPvAnimationItemWidget(),
)
),
Positioned(
left: 100,
top: 15,
child: RaisedButton(
child: Text('向右启动动画'),
onPressed: (){
setState(() {
model.action = 'restart';
model.direction = YJPvAnimationDirection.right;
});
},
),
),
Positioned(
left: 250,
top: 15,
child: RaisedButton(
child: Text('向左启动动画'),
onPressed: (){
setState(() {
model.action = 'restart';
model.direction = YJPvAnimationDirection.left;
});
},
),
),
],
),
)
);
}
}
class YJPvAnimationItemWidget extends StatefulWidget {
@override
_YJPvAnimationItemWidgetState createState() => _YJPvAnimationItemWidgetState();
}
class _YJPvAnimationItemWidgetState extends State<YJPvAnimationItemWidget> with TickerProviderStateMixin {
Animation<Size> _widthUpAni;
Animation<Size> _widthDownAni;
AnimationController _controllerUp;
AnimationController _controllerDown;
bool _isWidthShrink; //是否正在收缩状态
YJPvAnimationDirection _direction;
static const double _minWidth = 10;
static const double _maxWidth = 50;
@override
void initState() {
// TODO: implement initState
super.initState();
print('initState');
_isWidthShrink = false;
_direction = YJPvAnimationDirection.right;
_initController();
_initAni();
_start();
}
Future _start() async{
await _controllerUp.forward();
}
void _initController(){
_controllerUp = AnimationController(
duration: Duration(milliseconds: 500),
vsync: this,
);
_controllerDown = AnimationController(
duration: Duration(milliseconds: 500),
vsync: this,
);
}
void _initAni(){
_widthUpAni = SizeTween(
begin: Size.fromWidth(_minWidth),
end: Size.fromWidth(_maxWidth),
).animate(
CurvedAnimation(
parent: _controllerUp,
curve: Interval(0, 1, curve: Curves.fastOutSlowIn
),
),
)
..addListener((){
setState(() {});
})
..addStatusListener((AnimationStatus status){
print('--------------1');
print(status);
if (status == AnimationStatus.completed) {
_isWidthShrink = true;
_controllerDown.forward();
}
});
_widthDownAni = SizeTween(
begin: Size.fromWidth(_maxWidth),
end: Size.fromWidth(_minWidth),
).animate(
CurvedAnimation(
parent: _controllerDown,
curve: Interval(0, 1, curve: Curves.fastOutSlowIn
),
),
)
..addListener((){
setState(() {});
})
..addStatusListener((AnimationStatus status){
print('--------------2');
print(status);
if (_widthDownAni.status == AnimationStatus.completed ) {
_isWidthShrink = false;
_controllerUp.reset();
_controllerDown.reset();
}
});
}
@override
Widget build(BuildContext context) {
//宽度变化
double _width = _isWidthShrink ? _widthDownAni.value.width : _widthUpAni.value.width;
//margin变化
double _margin = _isWidthShrink ? (_maxWidth - 10 + _maxWidth - _widthDownAni.value.width) : (_widthUpAni.value.width - 10);
return Container(
height: 10,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(5)),
),
width: _width,
margin: _direction == YJPvAnimationDirection.left ? EdgeInsets.only(right: _margin) : EdgeInsets.only(left: _margin),
);
}
@override
void didChangeDependencies() {
print('didChangeDependencies');
// TODO: implement didChangeDependencies
super.didChangeDependencies();
final ctx = YJPvAnimationSharedContext.of(context);
if (ctx.model.action == 'restart') {
_direction = ctx.model.direction;
_start();
}
}
@override
void didUpdateWidget(YJPvAnimationItemWidget oldWidget) {
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
print('didUpdateWidget${oldWidget.runtimeType.hashCode}');
}
@override
void dispose() {
print('dispose');
// TODO: implement dispose
_controllerUp.dispose();
super.dispose();
}
}