Flutter 類抽屜效果動畫實現。

舟1478529607435發表於2019-10-23

效果:

豎向抽屜:

Flutter 類抽屜效果動畫實現。    Flutter 類抽屜效果動畫實現。

橫向抽屜:

Flutter 類抽屜效果動畫實現。


實現思路

  •  在STACK 容器裡建立3個頁面.
    具體程式碼如下:

    child: Stack(        
                children: <Widget>[        
                 Container(            
                   color: widget?.backgroundColor,             
                   child: buildContent(),         
                  ),        
                buildTop(),        
               buildRight(),        
            ],),複製程式碼

  •  通過監聽onVerticalDragUpdate和onHorizontalDragUpdate 獲取屬相和橫向滑動的座標資訊
            onVerticalDragUpdate: _inContent
                ? (details) {
                    calculateOffsetY(
                        details,
                        ((widget?.topPopConfig?.topMaxHeight ?? 0) <= 0
                                ? _height
                                : (widget?.topPopConfig?.topMaxHeight ?? 0)) -
                            (widget?.topPopConfig?.topMinHeight ?? 0));
                  }
                : null,
    
    
    
    複製程式碼

  • 用Transform包裹抽屜實現根據滑動位移而偏移

    class TopPop extends StatelessWidget {
      final double offsetY;
      final double height;
      final double minHeight;
      final double parentHeight;
      final Widget child;
      final Color backgroupColor;
      final bool needDarker;
      final GestureTapCallback onDarkerTap;
    
      TopPop(
          {Key key,
          this.offsetY = 0.0,
          this.height = 0.0,
          this.minHeight = 0.0,
          this.parentHeight = 0.0,
          this.child,
          this.backgroupColor,
          this.needDarker = false,
          this.onDarkerTap})
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        double tempOffsetY = 0.0;
        if (offsetY >= 0.0) {
          tempOffsetY = max(0.0, (parentHeight - minHeight));
        } else {
          tempOffsetY = offsetY + max(0.0, (parentHeight - minHeight));
        }
        double opacity = offsetY.abs() / height;
        debugPrint(
            '++++++++offsetY = ${offsetY.toString()}+++++++++opacity = ${opacity.toString()}+++++parentHeight= ${parentHeight.toString()}++ height=${height.toString()}++++++++++minHeight=${minHeight.toString()}+++++++++++++++++++');
        return Stack(
          children: <Widget>[
            needDarker && opacity > 0
                ? GestureDetector(
                    onTap: onDarkerTap,
                    child: Opacity(
                      opacity: opacity,
                      child: Container(
                        width: MediaQuery.of(context).size.width,
                        height: parentHeight,
                        color: Color(0x4C000000),
                      ),
                    ),
                  )
                : Container(),
            Transform.translate(
                offset: Offset(0, tempOffsetY),
                child: Container(
                  color: backgroupColor ?? Color(0x00000000),
                  width: MediaQuery.of(context).size.width,
                  height: height,
                  child: child,
                ))
          ],
        );
      }
    }
    
    
    
    複製程式碼
  • 監聽拖動結束事件,並實現自動滑動動畫。

            onVerticalDragEnd: (_) {
              if (_offsetY.abs() >
                      (widget?.topPopConfig?.topAutoAnimDistance ?? 20) &&
                  topDirection == AxisDirection.up) {
                animateToTop();
              } else {
                animateToBottom();
              }
            },
    
    
    複製程式碼

  • 監聽拖動開始事件,重置自動滑動動畫

            onVerticalDragStart: (_) {
              _animationControllerX?.stop();
              _animationControllerY?.stop();
            },
    
    
    複製程式碼

程式碼地址:
github.com/sail-coder/…


相關文章