当平移结束时,我有以下代码可以为Positioned
小部件(位置)设置动画。但是,它没有动画。
初始化AnimationController
和变量:
AnimationController nodesListAnimationController;
Animation<double> nodesListAnimation;
double nodesListOffsetY = 0.0; //widget default offset (will be large, but acts like 0.0)
double nodesListDragOffsetY = 0.0; //how far we have moved the widget from default offset (nodesListOffsetY)
double nodesListTouchOffset = 0.0; //the initial touch when drag begins
final double nodesListHeight = 350.0; //widget height
@override
void initState() {
super.initState();
nodesListAnimationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 350),
)
..addListener((){
setState(() {
});
});
}
构建功能;请参见Positioned
小部件。我可以使用GestureDetector
上的平移回调在创建的范围内上下拖动。
当平移结束时,我想将Positioned
小部件动画化回给定位置。当前,没有动画。
@override
Widget build(BuildContext context) {
nodesListOffsetY = MediaQuery.of(context).size.width + 110.0;
AppBar appBar = AppBar(
...
);
return Scaffold(
appBar: appBar,
backgroundColor: Colors.black,
body: Stack(
children: <Widget>[
Column(
children: <Widget>[
cameraWidget(),
cameraControls(),
],
),
Positioned(
left: 0.0,
top: nodesListAnimationController.isAnimating ? nodesListAnimation.value : nodesListOffsetY + nodesListDragOffsetY,
width: MediaQuery.of(context).size.width,
height: nodesListHeight,
child: GestureDetector(
onPanStart: (dragDetails) {
nodesListTouchOffset = (dragDetails.globalPosition.dy - appBar.preferredSize.height) - nodesListOffsetY - nodesListDragOffsetY;
},
onPanUpdate: (dragDetails) {
setState(() {
double newDragOffset = (dragDetails.globalPosition.dy - nodesListOffsetY) - appBar.preferredSize.height - nodesListTouchOffset;
//allow it only to move up if is clips off screen, otherwise upper limit not needed
double nodesListVisible = ((MediaQuery.of(context).size.height - appBar.preferredSize.height) - nodesListOffsetY);
bool isClipping = nodesListVisible < nodesListHeight ? true : false;
double upperLimit = 0.0;
if (isClipping) upperLimit = -(nodesListHeight - nodesListVisible);
//limit drag bounds. don't drag too high or low.
if (newDragOffset < upperLimit) newDragOffset = upperLimit;
else if (newDragOffset > 0) newDragOffset = 0.0;
else nodesListDragOffsetY = newDragOffset;
});
},
onPanEnd: (dragDetails) {
double currentPos = (nodesListOffsetY + nodesListDragOffsetY);
nodesListAnimation = Tween(begin: currentPos, end: nodesListOffsetY).animate(nodesListAnimationController);
nodesListAnimationController.forward(from: currentPos);
nodesListAnimation.addStatusListener((state) {
print(nodesListAnimation.value);
});
},
child: nodesList(),
),
),
],
));
}
答案 0 :(得分:0)
迟到了聚会,但您遇到的问题是因为:
nodesListAnimationController.forward(from: currentPos)
from
错误地接受了 0.0-1.0 之外的值。因此,您应该将其更改为controller.forward()
此文档没有很好的记录,但是正向from
的意思是接受 0.0-1.0 中的值,或更具体地说,如果已设置,则接受{{1}提供的范围}和lowerBound
(除少数例外)。 (您也可以将其视为0-100%)。这并不意味着接受Tween的upperBound
和begin
的值范围,也不知道该范围。
https://api.flutter.dev/flutter/animation/AnimationController-class.html
默认情况下,AnimationController线性生成的值范围是0.0到1.0
https://flutter.dev/docs/development/ui/animations/overview#addstatuslistener
然后动画可能会向前播放(例如,从0.0到1.0)
(而且我可以验证,将代码更改为仅使用end
之后,我才能看到它有动画效果)