效果:
豎向抽屜:
橫向抽屜:
實現思路
- 在STACK 容器裡建立3個頁面.
具體程式碼如下:
- 通過監聽onVerticalDragUpdate和onHorizontalDragUpdate 獲取屬相和橫向滑動的座標資訊
onVerticalDragUpdate: _inContent ? (details) { calculateOffsetY( details, ((widget?.topPopConfig?.topMaxHeight ?? 0) <= 0 ? _height : (widget?.topPopConfig?.topMaxHeight ?? 0)) - (widget?.topPopConfig?.topMinHeight ?? 0)); } : null, 複製程式碼
child: Stack(
children: <Widget>[
Container(
color: widget?.backgroundColor,
child: buildContent(),
),
buildTop(),
buildRight(),
],),複製程式碼
- 用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/…