diff --git a/CHANGELOG.md b/CHANGELOG.md index 15028df34df48f83194263aea329f5b2a04df846..e624ad74f5f53e8e103d6aaac4bb5ff38008a3b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## [0.5.5] +* TODO: Popover娣诲姞浜嗛槾褰辨晥鏋� +* TODO: Popover 娣诲姞浜嗘柟鍚� + ## [0.5.4] * TODO: Fix Bug Issues:47 diff --git a/documents/popover.md b/documents/popover.md index ed956f9a2ee3e05070aa3d82ad62532b00d49b29..28c3f6c898c9a463e0f18cc65758b17c461211c9 100644 --- a/documents/popover.md +++ b/documents/popover.md @@ -8,9 +8,11 @@ CupertinoPopoverButton({ this.child, this.popoverBuild, this.popoverColor=Colors.white, + this.popoverBoxShadow, @required this.popoverWidth, @required this.popoverHeight, BoxConstraints popoverConstraints, + this.direction = CupertinoPopoverDirection.bottom, this.onTap, this.transitionDuration=const Duration(milliseconds: 200), this.barrierColor = Colors.black54, @@ -25,8 +27,10 @@ CupertinoPopoverButton({ | [popoverWidth] | <code>double</code> | | 寮瑰嚭妗嗙殑瀹藉害 | | [popoverHeight] | <code>double</code> | | 寮瑰嚭妗嗙殑楂樺害 | | [popoverConstraints] | <code>BoxConstraints</code> | maxHeight:123.0 maxWidth:150.0 | 寮瑰嚭妗嗙殑鏈€澶ф渶灏忛珮瀹絴 +| [direction] | <code>CupertinoPopoverDirection</code> | CupertinoPopoverDirection.bottom | 鏂瑰悜| | [onTap] | <code>BoolCallback</code> | | 鎸夐挳鐐瑰嚮浜嬩欢,杩斿洖true鍙栨秷榛樿鍙嶅簲(涓嶆墦寮€Popover) | | [popoverColor] | <code>Color</code> | 鐧借壊 | 寮瑰嚭妗嗙殑鑳屾櫙棰滆壊 | +| [popoverBoxShadow] | <code>BoxShadow</code> | | 寮瑰嚭妗嗙殑闃村奖 | | [barrierColor] | <code>Color</code> | Colors.black54 | 閬僵灞傜殑棰滆壊,鐩墠涓嶅厑璁歌缃€忔槑,濡傞渶瑕侀€忔槑鍒欎娇鐢–olor.fromRGBO(0, 0, 0, 0.01)鍙揪鍒扮被浼兼晥鏋渱 | [transitionDuration] | <code>Duration</code> | 0.2s | 杩囧害鍔ㄧ敾鏃堕棿 | | [radius] | <code>double</code> | 8.0 | 寮瑰嚭妗嗙殑鍦嗚寮у害 | @@ -77,6 +81,8 @@ const CupertinoPopoverMenuItem({ this.leading, this.child, this.onTap, + this.background = Colors.white, + this.activeBackground = const Color(0xFFd9d9d9), this.isTapClosePopover=true }); ``` @@ -85,6 +91,8 @@ const CupertinoPopoverMenuItem({ | [leading] | <code>Widget<Widget></code> | 鑿滃崟宸﹁竟,涓€鑸斁鍥炬爣 | | [child] | <code>Widget<Widget></code> | 鑿滃崟鍐呭 | | [onTap] | <code>BoolCallback</code> | | 鎸夐挳鐐瑰嚮浜嬩欢,杩斿洖true鍙栨秷榛樿鍙嶅簲(涓嶅叧闂璓opover) | +| [activeBackground] | <code>Color</code> | Color(0xFFd9d9d9) | 鎸変笅鏃惰儗鏅壊 | +| [background] | <code>Color</code> | Colors.white | 榛樿鑳屾櫙鑹� | | [isTapClosePopover] | <code>bool<Widget></code> | 鏄惁鐐瑰嚮鍏抽棴 | #### 妗堜緥鏍稿績浠g爜 diff --git a/example/lib/pages/popover_demo.dart b/example/lib/pages/popover_demo.dart index 965644941ea1e13df5549d1efc5a85bfbd57af8b..bc155da431b4287d7e082d9cfd6709f897f478cc 100644 --- a/example/lib/pages/popover_demo.dart +++ b/example/lib/pages/popover_demo.dart @@ -60,6 +60,10 @@ class PopoverDemoState extends State<PopoverDemo>{ return Padding( padding: EdgeInsets.all(20.0), child:CupertinoPopoverButton( + popoverBoxShadow: [ + BoxShadow(color: Colors.black12,blurRadius: 5.0) + ], + barrierColor: Color(0x01FFFFFF), child: Container( width: 80.0, height: 40.0, diff --git a/lib/widgets/popover/cupertino_popover.dart b/lib/widgets/popover/cupertino_popover.dart index 35948ac7546434c0ab3c0829776ba48e49d801e5..cdd951a04af76bf37f08d9ec886e5d1c3acd3154 100644 --- a/lib/widgets/popover/cupertino_popover.dart +++ b/lib/widgets/popover/cupertino_popover.dart @@ -1,5 +1,10 @@ part of cool_ui; +enum CupertinoPopoverDirection{ + top, + bottom, +} + typedef BoolCallback = bool Function(); class CupertinoPopoverButton extends StatelessWidget{ final Widget child; @@ -7,19 +12,23 @@ class CupertinoPopoverButton extends StatelessWidget{ final double popoverWidth; final double popoverHeight; final Color popoverColor; + final List<BoxShadow> popoverBoxShadow; final double radius; final Duration transitionDuration; final BoolCallback onTap; final BoxConstraints popoverConstraints; final Color barrierColor; + final CupertinoPopoverDirection direction; CupertinoPopoverButton({ @required this.child, this.popoverBuild, this.popoverColor=Colors.white, + this.popoverBoxShadow, this.popoverWidth, this.popoverHeight, BoxConstraints popoverConstraints, + this.direction = CupertinoPopoverDirection.bottom, this.onTap, this.transitionDuration=const Duration(milliseconds: 200), this.barrierColor = Colors.black54, @@ -72,9 +81,11 @@ class CupertinoPopoverButton extends StatelessWidget{ child: body, constraints:popoverConstraints, color: popoverColor, + boxShadow: popoverBoxShadow, context: context, radius: radius, doubleAnimation: animation, + direction: direction, ), ); },); @@ -89,7 +100,9 @@ class CupertinoPopover extends StatefulWidget { final Rect attachRect; final Widget child; final Color color; + final List<BoxShadow> boxShadow; final double radius; + final CupertinoPopoverDirection direction; final Animation<double> doubleAnimation; BoxConstraints constraints; @@ -98,7 +111,9 @@ class CupertinoPopover extends StatefulWidget { @required this.child, BoxConstraints constraints, this.color=Colors.white, + this.boxShadow, @required BuildContext context, + this.direction = CupertinoPopoverDirection.bottom, this.doubleAnimation, this.radius=8.0}):super(){ BoxConstraints temp; @@ -150,12 +165,15 @@ class CupertinoPopoverState extends State<CupertinoPopover> with TickerProvider attachRect: widget.attachRect, scale: widget.doubleAnimation, constraints: widget.constraints, + direction: widget.direction, child: _CupertionPopoverContext( attachRect: widget.attachRect, scale: widget.doubleAnimation, radius: widget.radius, color: widget.color, - child: Material(child: widget.child), + boxShadow: widget.boxShadow, + direction: widget.direction, + child: Material(type: MaterialType.transparency, child: widget.child), ), ) ], @@ -169,12 +187,14 @@ class _CupertionPopoverPosition extends SingleChildRenderObjectWidget{ final Rect attachRect; final Animation<double> scale; final BoxConstraints constraints; + final CupertinoPopoverDirection direction; - _CupertionPopoverPosition({Widget child,this.attachRect,this.constraints,this.scale}):super(child:child); + _CupertionPopoverPosition({Widget child,this.attachRect,this.constraints,this.scale, this.direction}):super(child:child); @override RenderObject createRenderObject(BuildContext context) =>_CupertionPopoverPositionRenderObject( attachRect:attachRect, + direction: direction, constraints:constraints); @@ -182,6 +202,7 @@ class _CupertionPopoverPosition extends SingleChildRenderObjectWidget{ void updateRenderObject(BuildContext context, _CupertionPopoverPositionRenderObject renderObject) { renderObject ..attachRect = attachRect + ..direction = direction ..additionalConstraints = constraints; } @@ -194,6 +215,16 @@ class _CupertionPopoverPosition extends SingleChildRenderObjectWidget{ } class _CupertionPopoverPositionRenderObject extends RenderShiftedBox{ + + CupertinoPopoverDirection get direction => _direction; + CupertinoPopoverDirection _direction; + set direction(CupertinoPopoverDirection value) { + if (_direction == value) + return; + _direction = value; + markNeedsLayout(); + } + Rect get attachRect => _attachRect; Rect _attachRect; set attachRect(Rect value) { @@ -215,9 +246,10 @@ class _CupertionPopoverPositionRenderObject extends RenderShiftedBox{ } - _CupertionPopoverPositionRenderObject({RenderBox child,Rect attachRect,Color color,BoxConstraints constraints,Animation<double> scale}) : super(child){ + _CupertionPopoverPositionRenderObject({RenderBox child,Rect attachRect,Color color,BoxConstraints constraints,Animation<double> scale, CupertinoPopoverDirection direction}) : super(child){ this._attachRect = attachRect; this._additionalConstraints = constraints; + this._direction = direction; } @@ -233,8 +265,8 @@ class _CupertionPopoverPositionRenderObject extends RenderShiftedBox{ Offset calcOffset(Size size){ double bodyLeft = 0.0; - - var isArrowUp = _ScreenUtil.getInstance().screenHeight > attachRect.bottom + size.height + CupertinoPopoverState._arrowHeight; + CupertinoPopoverDirection calcDirection = _calcDirection(attachRect,size, direction); + if(attachRect.left > size.width / 2 && _ScreenUtil.getInstance().screenWidth - attachRect.right > size.width / 2){ //鍒ゆ柇鏄惁鍙互鍦ㄤ腑闂� @@ -245,7 +277,7 @@ class _CupertionPopoverPositionRenderObject extends RenderShiftedBox{ bodyLeft = _ScreenUtil.getInstance().screenWidth - 10.0 - size.width; } - if(isArrowUp){ + if(calcDirection == CupertinoPopoverDirection.bottom){ return Offset(bodyLeft,attachRect.bottom); }else{ return Offset(bodyLeft,attachRect.top - size.height - CupertinoPopoverState._arrowHeight); @@ -263,15 +295,19 @@ class _CupertionPopoverPositionRenderObject extends RenderShiftedBox{ class _CupertionPopoverContext extends SingleChildRenderObjectWidget{ final Rect attachRect; final Color color; + final List<BoxShadow> boxShadow; final Animation<double> scale; final double radius; - _CupertionPopoverContext({Widget child,this.attachRect,this.color,this.scale,this.radius}):super(child:child); + final CupertinoPopoverDirection direction; + _CupertionPopoverContext({Widget child,this.attachRect,this.color, this.boxShadow,this.scale,this.radius, this.direction}):super(child:child); @override RenderObject createRenderObject(BuildContext context) => _CupertionPopoverContextRenderObject( attachRect: attachRect, color: color, - scale: scale, + boxShadow: boxShadow, + scale: scale.value, + direction: direction, radius: radius ); @@ -281,13 +317,25 @@ class _CupertionPopoverContext extends SingleChildRenderObjectWidget{ renderObject ..attachRect = attachRect ..color = color - ..scale = scale + ..boxShadow = boxShadow + ..scale = scale.value + ..direction = direction ..radius = radius; } } class _CupertionPopoverContextRenderObject extends RenderShiftedBox{ + CupertinoPopoverDirection get direction => _direction; + CupertinoPopoverDirection _direction; + set direction(CupertinoPopoverDirection value) { + if (_direction == value) + return; + _direction = value; + markNeedsLayout(); + } + + Rect get attachRect => _attachRect; Rect _attachRect; set attachRect(Rect value) { @@ -307,12 +355,22 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{ markNeedsLayout(); } - - Animation<double> get scale => _scale; - Animation<double> _scale; - set scale(Animation<double> value) { - if (_scale == value) + List<BoxShadow> get boxShadow => _boxShadow; + List<BoxShadow> _boxShadow; + set boxShadow(List<BoxShadow> value) { + if (_boxShadow == value) return; + _boxShadow = value; + markNeedsLayout(); + } + + + double get scale => _scale; + double _scale; + set scale(double value) { + // print('scale:${_scale.value}'); + // if (_scale == value) + // return; _scale = value; markNeedsLayout(); } @@ -328,11 +386,13 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{ } - _CupertionPopoverContextRenderObject({RenderBox child,Rect attachRect,Color color,Animation<double> scale,double radius}) : super(child){ + _CupertionPopoverContextRenderObject({RenderBox child,Rect attachRect,Color color, List<BoxShadow> boxShadow,double scale,double radius, CupertinoPopoverDirection direction}) : super(child){ this._attachRect = attachRect; this._color = color; + this._boxShadow = boxShadow; this._scale = scale; this._radius = radius; + this._direction = direction; } @@ -344,8 +404,8 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{ child.layout(childConstraints, parentUsesSize: true); size = Size(child.size.width,child.size.height + CupertinoPopoverState._arrowHeight); final BoxParentData childParentData = child.parentData; - var isArrowUp = _ScreenUtil.getInstance().screenHeight > attachRect.bottom + size.height + CupertinoPopoverState._arrowHeight; - if(isArrowUp) + CupertinoPopoverDirection calcDirection = _calcDirection(attachRect,size, direction); + if(calcDirection == CupertinoPopoverDirection.bottom) { childParentData.offset = Offset(0.0, CupertinoPopoverState._arrowHeight); } @@ -356,12 +416,14 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{ // TODO: implement paint Matrix4 transform = Matrix4.identity(); // - var isArrowUp = _ScreenUtil.getInstance().screenHeight > attachRect.bottom + size.height + CupertinoPopoverState._arrowHeight; + + CupertinoPopoverDirection calcDirection = _calcDirection(attachRect,size, direction); + var isArrowUp = calcDirection == CupertinoPopoverDirection.bottom; var arrowLeft =attachRect.left + attachRect.width / 2 - CupertinoPopoverState._arrowWidth / 2 - offset.dx; var translation = Offset(arrowLeft + CupertinoPopoverState._arrowWidth / 2,isArrowUp?0.0:size.height); transform.translate(translation.dx, translation.dy); - transform.scale(scale.value, scale.value, 1.0); + transform.scale(scale, scale, 1.0); transform.translate(-translation.dx, -translation.dy); Rect arrowRect = Rect.fromLTWH( arrowLeft, @@ -370,20 +432,40 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{ CupertinoPopoverState._arrowHeight); Rect bodyRect = Offset(0.0, isArrowUp?CupertinoPopoverState._arrowHeight:0.0) & child.size; + _paintShadows(context, transform, offset, isArrowUp,arrowRect,bodyRect); + + Path clipPath = _getClip(isArrowUp,arrowRect,bodyRect); context.pushClipPath(needsCompositing, offset,offset & size, - getClip(size,isArrowUp,arrowRect,bodyRect),(context,offset){ + clipPath,(context,offset){ context.pushTransform(needsCompositing, offset, transform,(context,offset){ final Paint backgroundPaint = Paint(); backgroundPaint.color = color; context.canvas.drawRect(offset & size, backgroundPaint); super.paint(context,offset); }); + }); } - Path getClip(Size size,bool isArrowUp,Rect arrowRect,Rect bodyRect) { + + void _paintShadows(PaintingContext context, Matrix4 transform, Offset offset, bool isArrowUp,Rect arrowRect,Rect bodyRect) { + if (boxShadow == null) + return; + for (final BoxShadow boxShadow in boxShadow) { + final Paint paint = boxShadow.toPaint(); + arrowRect = arrowRect.shift(offset).shift(boxShadow.offset).inflate(boxShadow.spreadRadius); + bodyRect = bodyRect.shift(offset).shift(boxShadow.offset).inflate(boxShadow.spreadRadius); + Path path = _getClip(isArrowUp, arrowRect, bodyRect); + + context.pushTransform(needsCompositing, offset, transform,(context,offset){ + context.canvas.drawPath(path,paint); + }); + } + } + + Path _getClip(bool isArrowUp,Rect arrowRect,Rect bodyRect) { Path path = new Path(); if(isArrowUp) @@ -437,4 +519,18 @@ class _CupertionPopoverContextRenderObject extends RenderShiftedBox{ path.close(); return path; } + +} + +CupertinoPopoverDirection _calcDirection(Rect attachRect,Size size, CupertinoPopoverDirection direction) { + bool isArrowUp; + switch(direction){ + case CupertinoPopoverDirection.top: + isArrowUp = attachRect.top < size.height + CupertinoPopoverState._arrowHeight; // 鍒ゆ柇椤堕儴浣嶇疆澶熶笉澶� + break; + case CupertinoPopoverDirection.bottom: + isArrowUp = _ScreenUtil.getInstance().screenHeight > attachRect.bottom + size.height + CupertinoPopoverState._arrowHeight; + break; + } + return isArrowUp ? CupertinoPopoverDirection.bottom : CupertinoPopoverDirection.top; } \ No newline at end of file diff --git a/lib/widgets/popover/cupertino_popover_menu_item.dart b/lib/widgets/popover/cupertino_popover_menu_item.dart index 1222f3f721fa50515e17184c10818b576e25c9dd..17bc0fe4e1adeee786c78e0468395b623f5f8e9b 100644 --- a/lib/widgets/popover/cupertino_popover_menu_item.dart +++ b/lib/widgets/popover/cupertino_popover_menu_item.dart @@ -1,106 +1,102 @@ part of cool_ui; - -class CupertinoPopoverMenuList extends StatelessWidget{ +class CupertinoPopoverMenuList extends StatelessWidget { final List<Widget> children; const CupertinoPopoverMenuList({this.children}); @override Widget build(BuildContext context) { return ListView.builder( - itemCount: children.length * 2 - 1, - shrinkWrap: true, - itemBuilder: (context,int i){ - if(i.isOdd){ - // 鍦ㄦ瘡涓€鍒椾箣鍓嶏紝娣诲姞涓€涓�1鍍忕礌楂樼殑鍒嗛殧绾縲idget - return const Divider(height: 1.0,); - } - final int index=i ~/2; - return children[index]; - }, - padding: EdgeInsets.all(0.0), - + itemCount: children.length * 2 - 1, + shrinkWrap: true, + itemBuilder: (context, int i) { + if (i.isOdd) { + // 鍦ㄦ瘡涓€鍒椾箣鍓嶏紝娣诲姞涓€涓�1鍍忕礌楂樼殑鍒嗛殧绾縲idget + return const Divider( + height: 1.0, + ); + } + final int index = i ~/ 2; + return children[index]; + }, + padding: EdgeInsets.all(0.0), ); } - } - -class CupertinoPopoverMenuItem extends StatefulWidget{ +class CupertinoPopoverMenuItem extends StatefulWidget { final Widget leading; final Widget child; final BoolCallback onTap; final bool isTapClosePopover; + final Color activeBackground; + final Color background; - const CupertinoPopoverMenuItem({ - this.leading, - this.child, - this.onTap, - this.isTapClosePopover=true - }); + const CupertinoPopoverMenuItem( + {this.leading, + this.child, + this.onTap, + this.background = Colors.white, + this.activeBackground = const Color(0xFFd9d9d9), + this.isTapClosePopover = true}); @override - State<StatefulWidget> createState() =>CupertinoPopoverMenuItemState(); + State<StatefulWidget> createState() => CupertinoPopoverMenuItemState(); } -class CupertinoPopoverMenuItemState extends State<CupertinoPopoverMenuItem>{ +class CupertinoPopoverMenuItemState extends State<CupertinoPopoverMenuItem> { bool isDown = false; @override Widget build(BuildContext context) { List<Widget> widgets = []; - if(widget.leading != null){ + if (widget.leading != null) { widgets.add(Container( - padding: EdgeInsets.only(left:5.0,right: 5.0), + padding: EdgeInsets.only(left: 5.0, right: 5.0), width: 35.0, height: 35.0, child: IconTheme( - data:IconThemeData(color: Color(0xff007aff),size: 20.0), - child: widget.leading - ), + data: IconThemeData(color: Color(0xff007aff), size: 20.0), + child: widget.leading), )); } - widgets.add(Expanded(child: DefaultTextStyle(style: TextStyle( - color: Color(0xff007aff), - fontSize: 17.0 - ), child: widget.child))); + widgets.add(Expanded( + child: DefaultTextStyle( + style: TextStyle(color: Color(0xff007aff), fontSize: 17.0), + child: widget.child))); return GestureDetector( - onTapDown: (detail){ + onTapDown: (detail) { setState(() { isDown = true; }); }, - onTapUp: (detail){ - if(isDown){ + onTapUp: (detail) { + if (isDown) { setState(() { isDown = false; }); - if(widget.onTap != null && widget.onTap()){ + if (widget.onTap != null && widget.onTap()) { return; } - if(widget.isTapClosePopover){ + if (widget.isTapClosePopover) { Navigator.of(context).pop(); } } }, - onTapCancel: (){ - if(isDown){ + onTapCancel: () { + if (isDown) { setState(() { isDown = false; }); } }, child: Container( - color:isDown?Color(0xFFd9d9d9):Colors.white, + color: isDown ? widget.activeBackground : widget.background, child: Padding( - padding: EdgeInsets.only(top:2.5,bottom: 2.5), - child: Row( - children: widgets - ), + padding: EdgeInsets.only(top: 2.5, bottom: 2.5), + child: Row(children: widgets), ), ), ); - } - -} \ No newline at end of file +} diff --git a/pubspec.yaml b/pubspec.yaml index 3ab165ce0d8350abee4da3788f6a920a999246a4..ad37a2da1d78fdf0815b5f524e002c8a973a7811 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: cool_ui description: Some practical Widget for flutter,Popover,Weui,Custom Keyboard -version: 0.5.4 +version: 0.5.5 author: Kevin <liangkaikevin@gmail.com> homepage: https://github.com/Im-Kevin/cool_ui