效果:
竖向抽屉:
横向抽屉:
实现思路
- 在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(); },