diff --git a/CHANGELOG.md b/CHANGELOG.md index a454b768a09f07d0857118a2179d09641f90b752..d63cf64aa9285f69eda8c5050db0a5855215e5d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## [0.1.5] - TODO:娣诲姞浜唒opoverConstraints鍙傛暟 +* TODO: CupertionPopoverButton娣诲姞浜咰upertionPopoverButton鍙傛暟,鐢ㄤ簬璁剧疆鏈€澶ф渶灏忓搴�,鍙栨秷蹇呭~鐨勯珮瀹� + ## [0.1.4] - TODO:淇敼浜唎nTap浜嬩欢 * TODO: CupertionPopoverButton娣诲姞浜唎nTap浜嬩欢,杩斿洖True涓嶆墦寮€Popover * TODO: CupertinoPopoverMenuItem淇敼浜唎nTap浜嬩欢,杩斿洖True涓嶅叧闂璓opover diff --git a/README.md b/README.md index 72dae2fa5597f2b3ded3bb374fe75e18bc29d859..e65ad033b95e59aa577916766cdc29393d1a628a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Usage Add this to your package's pubspec.yaml file: ``` yaml dependencies: - cool_ui: "^0.1.4" + cool_ui: "^0.1.5" ``` # 鎺т欢 @@ -31,6 +31,7 @@ CupertinoPopoverButton({ this.popoverColor=Colors.white, @required this.popoverWidth, @required this.popoverHeight, + BoxConstraints popoverConstraints, this.onTap, this.transitionDuration=const Duration(milliseconds: 200), this.radius=8.0}); @@ -41,8 +42,9 @@ CupertinoPopoverButton({ | --- | --- | --- | --- | | child | <code>Widget</code> | | 鎸夐挳鐨勫唴瀹� | | popoverBuild | <code>WidgetBuilder</code> | | 鐢熸垚寮瑰嚭妗嗙殑鍐呭 | -| popoverWidth | <code>double</code> | | 寮瑰嚭妗嗙殑瀹藉害 | -| popoverHeight | <code>double</code> | | 寮瑰嚭妗嗙殑楂樺害 | +| [popoverWidth] | <code>double</code> | | 寮瑰嚭妗嗙殑瀹藉害 | +| [popoverHeight] | <code>double</code> | | 寮瑰嚭妗嗙殑楂樺害 | +| [popoverConstraints] | <code>BoxConstraints</code> | maxHeight:123.0 maxWidth:150.0 | 寮瑰嚭妗嗙殑鏈€澶ф渶灏忛珮瀹絴 | [onTap] | <code>BoolCallback</code> | | 鎸夐挳鐐瑰嚮浜嬩欢,杩斿洖true鍙栨秷榛樿鍙嶅簲(涓嶆墦寮€Popover) | | [popoverColor] | <code>Color</code> | 鐧借壊 | 寮瑰嚭妗嗙殑鑳屾櫙棰滆壊 | | [transitionDuration] | <code>Duration</code> | 0.2s | 杩囧害鍔ㄧ敾鏃堕棿 | @@ -70,9 +72,7 @@ CupertinoPopoverButton( height: 100.0, child: Text('宸︿笂瑙掑唴瀹�'), ) - }, - popoverWidth: 100.0, - popoverHeight: 100.0); + }); ```  diff --git a/example/lib/pages/popover_demo.dart b/example/lib/pages/popover_demo.dart index 8b2d7eb8ddd07b434ec82ed266fe6689260485c2..965644941ea1e13df5549d1efc5a85bfbd57af8b 100644 --- a/example/lib/pages/popover_demo.dart +++ b/example/lib/pages/popover_demo.dart @@ -60,7 +60,6 @@ class PopoverDemoState extends State<PopoverDemo>{ return Padding( padding: EdgeInsets.all(20.0), child:CupertinoPopoverButton( - child: Container( width: 80.0, height: 40.0, @@ -72,6 +71,7 @@ class PopoverDemoState extends State<PopoverDemo>{ child: Center(child:Text(btnTitle)), ), popoverBuild: (context) { +// return Text("satatastas"); return CupertinoPopoverMenuList( children: <Widget>[ CupertinoPopoverMenuItem(leading: Icon(Icons.add),child: Text("鏂板"),), @@ -79,9 +79,7 @@ class PopoverDemoState extends State<PopoverDemo>{ CupertinoPopoverMenuItem(leading: Icon(Icons.delete),child: Text("鍒犻櫎"),) ], ); - }, - popoverWidth: 150.0, - popoverHeight: 123.0) + }) ); diff --git a/lib/widgets/popover/cupertino_popover.dart b/lib/widgets/popover/cupertino_popover.dart index 5fc0a88155164d173db15c8b3d84ebb9cdafe0bc..b35c73d053320b3824ecb6acc7441b582f68ba06 100644 --- a/lib/widgets/popover/cupertino_popover.dart +++ b/lib/widgets/popover/cupertino_popover.dart @@ -11,7 +11,9 @@ class CupertinoPopoverButton extends StatelessWidget{ final double radius; final Duration transitionDuration; final BoolCallback onTap; - const CupertinoPopoverButton({ + final BoxConstraints popoverConstraints; + + CupertinoPopoverButton({ @required this.child, @Deprecated( '寤鸿涓嶈鐩存帴浣跨敤popoverBody,鑰屾槸浣跨敤popoverBuild.' @@ -19,14 +21,20 @@ class CupertinoPopoverButton extends StatelessWidget{ this.popoverBody, this.popoverBuild, this.popoverColor=Colors.white, - @required this.popoverWidth, - @required this.popoverHeight, + this.popoverWidth, + this.popoverHeight, + BoxConstraints popoverConstraints, this.onTap, this.transitionDuration=const Duration(milliseconds: 200), this.radius=8.0}): assert(popoverBody != null || popoverBuild != null), - assert(!(popoverBody != null && popoverBuild != null)); + assert(!(popoverBody != null && popoverBuild != null)), + this.popoverConstraints = + (popoverWidth != null || popoverHeight != null) + ? popoverConstraints?.tighten(width: popoverWidth, height: popoverHeight) + ?? BoxConstraints.tightFor(width: popoverWidth, height: popoverHeight) + : popoverConstraints; @override Widget build(BuildContext context) { @@ -66,8 +74,7 @@ class CupertinoPopoverButton extends StatelessWidget{ child: CupertinoPopover( attachRect:Rect.fromLTWH(offset.dx, offset.dy, bounds.width, bounds.height), child: body, - width: popoverWidth, - height: popoverHeight, + constraints:popoverConstraints, color: popoverColor, context: context, radius: radius, @@ -81,41 +88,54 @@ class CupertinoPopoverButton extends StatelessWidget{ } } - class CupertinoPopover extends StatefulWidget { final Rect attachRect; final Widget child; - final double width; - final double height; final Color color; final double radius; final Animation<double> doubleAnimation; + BoxConstraints constraints; CupertinoPopover({ @required this.attachRect, @required this.child, - @required this.width, - @required this.height, + BoxConstraints constraints, this.color=Colors.white, @required BuildContext context, this.doubleAnimation, this.radius=8.0}):super(){ ScreenUtil.getInstance().init(context); + BoxConstraints temp = null; + if(constraints != null){ + temp = BoxConstraints(maxHeight:123.0,maxWidth:150.0).copyWith( + minWidth: constraints.minWidth.isFinite?constraints.minWidth:null, + minHeight: constraints.minHeight.isFinite?constraints.minHeight:null, + maxWidth: constraints.maxWidth.isFinite?constraints.maxWidth:null, + maxHeight: constraints.maxHeight.isFinite?constraints.maxHeight:null, + ); + }else{ + temp=BoxConstraints(maxHeight:123.0,maxWidth:150.0); + } + this.constraints = temp.copyWith(maxHeight: temp.maxHeight + CupertinoPopoverState._arrowHeight); } @override CupertinoPopoverState createState() => new CupertinoPopoverState(); + + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, showName: false)); + properties.add(DiagnosticsProperty<Color>('color', color, showName: false)); + properties.add(DiagnosticsProperty<double>('double', radius, showName: false)); + } } class CupertinoPopoverState extends State<CupertinoPopover> with TickerProviderStateMixin{ static const double _arrowWidth = 12.0; static const double _arrowHeight = 8.0; - double left; - double top; - Rect _arrowRect; - Rect _bodyRect; - // AnimationController animation; /// 鏄惁绠ご鍚戜笂 @@ -123,87 +143,251 @@ class CupertinoPopoverState extends State<CupertinoPopover> with TickerProvider @override void initState() { - // TODO: implement initState - isArrowUp = ScreenUtil.screenHeight > widget.attachRect.bottom + widget.height + _arrowWidth; super.initState(); - calcRect(); } @override Widget build(BuildContext context) { - - var bodyMiddleX = _bodyRect.left + _bodyRect.width / 2; // 璁$畻Body鐨刋杞翠腑闂寸偣 - var arrowMiddleX = _arrowRect.left + _arrowRect.width /2; //璁$畻绠ご鐨刋杞翠腑闂寸偣 - var leftOffset = (arrowMiddleX - bodyMiddleX) * (1 - widget.doubleAnimation.value); //璁$畻X杞寸缉灏忕殑鍋忕Щ鍊� return Stack( - children: <Widget>[ - Positioned( - left:left + leftOffset, - top:top, - child:ScaleTransition( - alignment: isArrowUp?Alignment.topCenter:Alignment.bottomCenter, - scale: widget.doubleAnimation, - child: ClipPath( - clipper:ArrowCliper( - arrowRect:_arrowRect, - bodyRect: _bodyRect, - isArrowUp: isArrowUp, - radius: widget.radius - ), - child: Container( - padding: EdgeInsets.only(top:isArrowUp?_arrowHeight:0.0), - color: Colors.white, - width: widget.width, - height: _bodyRect.height + _arrowHeight, - child: Material(child: widget.child) - ),), - ), - ) - ] + children: <Widget>[ + _CupertionPopoverPosition( + attachRect: widget.attachRect, + scale: widget.doubleAnimation, + constraints: widget.constraints, + child: _CupertionPopoverContext( + attachRect: widget.attachRect, + scale: widget.doubleAnimation, + radius: widget.radius, + color: widget.color, + child: Material(child: widget.child), + ), + ) + ], ); } - calcRect(){ - double arrowLeft = 0.0; - double arrowTop = 0.0; - double bodyTop = 0.0; +} + + +class _CupertionPopoverPosition extends SingleChildRenderObjectWidget{ + final Rect attachRect; + final Animation<double> scale; + final BoxConstraints constraints; + + _CupertionPopoverPosition({Widget child,this.attachRect,this.constraints,this.scale}):super(child:child); + + @override + RenderObject createRenderObject(BuildContext context) =>_CupertionPopoverPositionRenderObject( + attachRect:attachRect, + constraints:constraints); + + + @override + void updateRenderObject(BuildContext context, _CupertionPopoverPositionRenderObject renderObject) { + renderObject + ..attachRect = attachRect + ..additionalConstraints = constraints; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, showName: false)); + } + +} + +class _CupertionPopoverPositionRenderObject extends RenderShiftedBox{ + Rect get attachRect => _attachRect; + Rect _attachRect; + set attachRect(Rect value) { + if (_attachRect == value) + return; + _attachRect = value; + markNeedsLayout(); + } + + + + BoxConstraints get additionalConstraints => _additionalConstraints; + BoxConstraints _additionalConstraints; + set additionalConstraints(BoxConstraints value) { + if (_additionalConstraints == value) + return; + _additionalConstraints = value; + markNeedsLayout(); + } + + + _CupertionPopoverPositionRenderObject({RenderBox child,Rect attachRect,Color color,BoxConstraints constraints,Animation<double> scale}) : super(child){ + this._attachRect = attachRect; + this._additionalConstraints = constraints; + } + + + @override + void performLayout() { + child.layout(_additionalConstraints.enforce(constraints), parentUsesSize: true); + size = Size(constraints.maxWidth,constraints.maxHeight); + + final BoxParentData childParentData = child.parentData; + + childParentData.offset = calcOffset(child.size); + } + + Offset calcOffset(Size size){ double bodyLeft = 0.0; - arrowLeft = widget.attachRect.left + widget.attachRect.width / 2 - _arrowWidth / 2; - if(widget.attachRect.left > widget.width / 2 && - ScreenUtil.screenWidth - widget.attachRect.right > widget.width / 2){ //鍒ゆ柇鏄惁鍙互鍦ㄤ腑闂� - bodyLeft = widget.attachRect.left + widget.attachRect.width / 2 - widget.width / 2; - }else if(widget.attachRect.left < widget.width / 2){ //闈犲乏 + var isArrowUp = ScreenUtil.screenHeight > attachRect.bottom + size.height + CupertinoPopoverState._arrowHeight; + + if(attachRect.left > size.width / 2 && + ScreenUtil.screenWidth - attachRect.right > size.width / 2){ //鍒ゆ柇鏄惁鍙互鍦ㄤ腑闂� + bodyLeft = attachRect.left + attachRect.width / 2 - size.width / 2; + }else if(attachRect.left < size.width / 2){ //闈犲乏 bodyLeft = 10.0; }else{ //闈犲彸 - bodyLeft = ScreenUtil.screenWidth - 10.0 - widget.width; + bodyLeft = ScreenUtil.screenWidth - 10.0 - size.width; } if(isArrowUp){ - arrowTop = widget.attachRect.bottom; - bodyTop = arrowTop + _arrowHeight; + return Offset(bodyLeft,attachRect.bottom); }else{ - arrowTop = widget.attachRect.top - _arrowHeight; - bodyTop = widget.attachRect.top - widget.height - _arrowHeight; + return Offset(bodyLeft,attachRect.top - size.height - CupertinoPopoverState._arrowHeight); } + } + - left = bodyLeft; - top = isArrowUp?arrowTop:bodyTop; - _arrowRect = Rect.fromLTWH(arrowLeft - left, arrowTop - top, _arrowWidth, _arrowHeight); - _bodyRect = Rect.fromLTWH(0.0, bodyTop - top, widget.width, widget.height); + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty<BoxConstraints>('additionalConstraints', additionalConstraints)); } } - -class ArrowCliper extends CustomClipper<Path>{ - final bool isArrowUp; - final Rect arrowRect; - final Rect bodyRect; +class _CupertionPopoverContext extends SingleChildRenderObjectWidget{ + final Rect attachRect; + final Color color; + final Animation<double> scale; final double radius; - const ArrowCliper({this.isArrowUp,this.arrowRect,this.bodyRect,this.radius = 13.0}); + _CupertionPopoverContext({Widget child,this.attachRect,this.color,this.scale,this.radius}):super(child:child); + + @override + RenderObject createRenderObject(BuildContext context) => _CupertionPopoverContextRenderObject( + attachRect: attachRect, + color: color, + scale: scale, + radius: radius + ); + + + @override + void updateRenderObject(BuildContext context, _CupertionPopoverContextRenderObject renderObject) { + renderObject + ..attachRect = attachRect + ..color = color + ..scale = scale + ..radius = radius; + } + +} + +class _CupertionPopoverContextRenderObject extends RenderShiftedBox{ + Rect get attachRect => _attachRect; + Rect _attachRect; + set attachRect(Rect value) { + if (_attachRect == value) + return; + _attachRect = value; + markNeedsLayout(); + } + + + Color get color => _color; + Color _color; + set color(Color value) { + if (_color == value) + return; + _color = value; + markNeedsLayout(); + } + + + Animation<double> get scale => _scale; + Animation<double> _scale; + set scale(Animation<double> value) { + if (_scale == value) + return; + _scale = value; + markNeedsLayout(); + } + + + double get radius => _radius; + double _radius; + set radius(double value) { + if (_radius == value) + return; + _radius = value; + markNeedsLayout(); + } + + + _CupertionPopoverContextRenderObject({RenderBox child,Rect attachRect,Color color,Animation<double> scale,double radius}) : super(child){ + this._attachRect = attachRect; + this._color = color; + this._scale = scale; + this._radius = radius; + } + @override - Path getClip(Size size) { + void performLayout() { + assert(constraints.maxHeight.isFinite); + BoxConstraints childConstraints = BoxConstraints(maxHeight: constraints.maxHeight - CupertinoPopoverState._arrowHeight).enforce(constraints); + + child.layout(childConstraints, parentUsesSize: true); + size = Size(child.size.width,child.size.height + CupertinoPopoverState._arrowHeight); + final BoxParentData childParentData = child.parentData; + var isArrowUp = ScreenUtil.screenHeight > attachRect.bottom + size.height + CupertinoPopoverState._arrowHeight; + if(isArrowUp) + { + childParentData.offset = Offset(0.0, CupertinoPopoverState._arrowHeight); + } + } + + @override + void paint(PaintingContext context, Offset offset) { + // TODO: implement paint + Matrix4 transform = Matrix4.identity(); +// + var isArrowUp = ScreenUtil.screenHeight > attachRect.bottom + size.height + CupertinoPopoverState._arrowHeight; + + 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.translate(-translation.dx, -translation.dy); + Rect arrowRect = Rect.fromLTWH( + arrowLeft, + isArrowUp?0.0:child.size.height, + CupertinoPopoverState._arrowWidth, + CupertinoPopoverState._arrowHeight); + Rect bodyRect = Offset(0.0, isArrowUp?CupertinoPopoverState._arrowHeight:0.0) & child.size; + + context.pushClipPath(needsCompositing, + offset,offset & size, + getClip(size,isArrowUp,arrowRect,bodyRect),(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) { Path path = new Path(); if(isArrowUp) @@ -257,10 +441,4 @@ class ArrowCliper extends CustomClipper<Path>{ path.close(); return path; } - - @override - bool shouldReclip(ArrowCliper oldClipper) { - return this.isArrowUp != oldClipper.isArrowUp || this.arrowRect != oldClipper.arrowRect || this.bodyRect != oldClipper.bodyRect; - } - } \ 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 f1260caefd4829884f31de4890086b65d7dea199..1222f3f721fa50515e17184c10818b576e25c9dd 100644 --- a/lib/widgets/popover/cupertino_popover_menu_item.dart +++ b/lib/widgets/popover/cupertino_popover_menu_item.dart @@ -8,16 +8,18 @@ class CupertinoPopoverMenuList extends StatelessWidget{ @override Widget build(BuildContext context) { return ListView.builder( - itemCount: children.length * 2 - 1, - 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), + ); } diff --git a/pubspec.lock b/pubspec.lock index 5527adef823e4dd2169047afa9b2a4a54561cfbe..20675055c18c92163b394592a8a873426435a744 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -76,13 +76,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_spinkit: - dependency: "direct main" - description: - name: flutter_spinkit - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.1.0" flutter_test: dependency: "direct dev" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index f4acba2e8891213585f23c7217ae1dd668d4e6b2..374bfb61d3cc39a280eaaf9db3f5673995f578a0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: cool_ui description: 鐢╢lutter瀹炵幇涓€浜涙垜璁や负濂界湅鐨刄I鎺т欢,鐩墠鏆傛椂鍙湁Popover,Weui锛屼笉杩囨湁浠€涔堣寰楀ソ鐪嬬殑鍙互鎻怚ssue -version: 0.1.4 +version: 0.1.5 author: Kevin <liangkaikevin@gmail.com> homepage: https://github.com/Im-Kevin/cool_ui