带有Flutter的定位小部件动画

时间:2018-08-02 12:22:44

标签: animation dart flutter

当平移结束时,我有以下代码可以为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(),
              ),
            ),
          ],
        ));
  }

1 个答案:

答案 0 :(得分:0)

迟到了聚会,但您遇到的问题是因为:

nodesListAnimationController.forward(from: currentPos)

from错误地接受了 0.0-1.0 之外的值。因此,您应该将其更改为controller.forward()

此文档没有很好的记录,但是正向from的意思是接受 0.0-1.0 中的值,或更具体地说,如果已设置,则接受{{1}提供的范围}和lowerBound(除少数例外)。 (您也可以将其视为0-100%)。这并不意味着接受Tween的upperBoundbegin的值范围,也不知道该范围。

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之后,我才能看到它有动画效果)