diff --git a/Classes/Popover.swift b/Classes/Popover.swift index 7f1d4b6..6618bf4 100644 --- a/Classes/Popover.swift +++ b/Classes/Popover.swift @@ -23,11 +23,14 @@ public enum PopoverOption { case showBlackOverlay(Bool) case springDamping(CGFloat) case initialSpringVelocity(CGFloat) + case sideOffset(CGFloat) } @objc public enum PopoverType: Int { case up case down + case left + case right case auto } @@ -50,6 +53,7 @@ open class Popover: UIView { open var highlightCornerRadius: CGFloat = 0 open var springDamping: CGFloat = 0.7 open var initialSpringVelocity: CGFloat = 3 + open var sideOffset: CGFloat = 6.0 // custom closure open var willShowHandler: (() -> ())? @@ -120,6 +124,7 @@ open class Popover: UIView { open func show(_ contentView: UIView, fromView: UIView, inView: UIView) { let point: CGPoint + //TODO: add left/right auto if self.popoverType == .auto { if let point = fromView.superview?.convert(fromView.frame.origin, to: nil), point.y + fromView.frame.height + self.arrowSize.height + contentView.frame.height > inView.frame.height { @@ -142,6 +147,16 @@ open class Popover: UIView { x: fromView.frame.origin.x + (fromView.frame.size.width / 2), y: fromView.frame.origin.y + fromView.frame.size.height ), from: fromView.superview) + case .left: + point = inView.convert( + CGPoint(x: fromView.frame.origin.x - sideOffset, + y: fromView.frame.origin.y + 0.5 * fromView.frame.height + ), from: fromView.superview) + case .right: + point = inView.convert( + CGPoint(x: fromView.frame.origin.x + fromView.frame.size.width + sideOffset, + y: fromView.frame.origin.y + 0.5 * fromView.frame.height + ), from: fromView.superview) } if self.highlightFromView { @@ -337,6 +352,118 @@ open class Popover: UIView { arrow.addLine(to: CGPoint( x: arrowPoint.x - self.arrowSize.width * 0.5, y: self.isCornerLeftArrow ? self.arrowSize.height + self.bounds.height : self.arrowSize.height)) + + case .left: + arrow.move(to: CGPoint(x: self.bounds.width, y: self.bounds.height * 0.5)) + arrow.addLine( + to: CGPoint( + x: self.bounds.width - self.arrowSize.height, + y: self.bounds.height * 0.5 + self.arrowSize.width * 0.5 + )) + + arrow.addLine(to: CGPoint(x:self.bounds.width - self.arrowSize.height, y: self.bounds.height - self.cornerRadius)) + arrow.addArc( + withCenter: CGPoint( + x: self.bounds.width - self.arrowSize.height - self.cornerRadius, + y: self.bounds.height - self.cornerRadius + ), + radius: self.cornerRadius, + startAngle: self.radians(0.0), + endAngle: self.radians(90), + clockwise: true) + + arrow.addLine(to: CGPoint(x: self.cornerRadius, y: self.bounds.height)) + arrow.addArc( + withCenter: CGPoint( + x: self.cornerRadius, + y: self.bounds.height - self.cornerRadius + ), + radius: self.cornerRadius, + startAngle: self.radians(90), + endAngle: self.radians(180), + clockwise: true) + + arrow.addLine(to: CGPoint(x: 0, y: self.cornerRadius)) + arrow.addArc( + withCenter: CGPoint( + x: self.cornerRadius, + y: self.cornerRadius + ), + radius: self.cornerRadius, + startAngle: self.radians(180), + endAngle: self.radians(270), + clockwise: true) + + arrow.addLine(to: CGPoint(x: self.bounds.width - self.arrowSize.height - self.cornerRadius, y: 0)) + arrow.addArc( + withCenter: CGPoint(x: self.bounds.width - self.arrowSize.height - self.cornerRadius, + y: self.cornerRadius + ), + radius: self.cornerRadius, + startAngle: self.radians(270), + endAngle: self.radians(0), + clockwise: true) + + arrow.addLine(to: CGPoint(x: self.bounds.width - self.arrowSize.height, + y: self.bounds.height * 0.5 - self.arrowSize.width * 0.5 + )) + case .right: + arrow.move(to: CGPoint(x: arrowPoint.x, y: self.bounds.height * 0.5)) + arrow.addLine( + to: CGPoint( + x: arrowPoint.x + self.arrowSize.height, + y: self.bounds.height * 0.5 + 0.5 * self.arrowSize.width + )) + + arrow.addLine( + to: CGPoint( + x: arrowPoint.x + self.arrowSize.height, + y: self.bounds.height - self.cornerRadius + )) + arrow.addArc( + withCenter: CGPoint( + x: arrowPoint.x + self.arrowSize.height + self.cornerRadius, + y: self.bounds.height - self.cornerRadius + ), + radius: self.cornerRadius, + startAngle: self.radians(180.0), + endAngle: self.radians(90), + clockwise: false) + + arrow.addLine(to: CGPoint(x: self.bounds.width + arrowPoint.x - self.cornerRadius, y: self.bounds.height)) + arrow.addArc( + withCenter: CGPoint( + x: self.bounds.width + arrowPoint.x - self.cornerRadius, + y: self.bounds.height - self.cornerRadius + ), + radius: self.cornerRadius, + startAngle: self.radians(90), + endAngle: self.radians(0), + clockwise: false) + + arrow.addLine(to: CGPoint(x: self.bounds.width + arrowPoint.x, y: self.cornerRadius)) + arrow.addArc( + withCenter: CGPoint( + x: self.bounds.width + arrowPoint.x - self.cornerRadius, + y: self.cornerRadius + ), + radius: self.cornerRadius, + startAngle: self.radians(0), + endAngle: self.radians(-90), + clockwise: false) + + arrow.addLine(to: CGPoint(x: arrowPoint.x + self.arrowSize.height - self.cornerRadius, y: 0)) + arrow.addArc( + withCenter: CGPoint(x: arrowPoint.x + self.arrowSize.height + self.cornerRadius, + y: self.cornerRadius + ), + radius: self.cornerRadius, + startAngle: self.radians(-90), + endAngle: self.radians(-180), + clockwise: false) + + arrow.addLine(to: CGPoint(x: arrowPoint.x + self.arrowSize.height, + y: self.bounds.height * 0.5 - self.arrowSize.width * 0.5)) } color.setFill() @@ -376,6 +503,8 @@ private extension Popover { self.springDamping = value case let .initialSpringVelocity(value): self.initialSpringVelocity = value + case let .sideOffset(value): + self.sideOffset = value } } } @@ -383,7 +512,13 @@ private extension Popover { func create() { var frame = self.contentView.frame - frame.origin.x = self.arrowShowPoint.x - frame.size.width * 0.5 + + switch self.popoverType { + case .up, .down, .auto: + frame.origin.x = self.arrowShowPoint.x - frame.size.width * 0.5 + case .left, .right: + frame.origin.y = self.arrowShowPoint.y - frame.size.height * 0.5 + } var sideEdge: CGFloat = 0.0 if frame.size.width < self.containerView.frame.size.width { @@ -409,6 +544,12 @@ private extension Popover { case .down, .auto: frame.origin.y = self.arrowShowPoint.y anchorPoint = CGPoint(x: arrowPoint.x / frame.size.width, y: 0) + case .left: + frame.origin.x = self.arrowShowPoint.x - frame.size.width - self.arrowSize.height + anchorPoint = CGPoint(x: 1, y: 0.5) + case .right: + frame.origin.x = self.arrowShowPoint.x + anchorPoint = CGPoint(x: 0, y: 0.5) } if self.arrowSize == .zero { @@ -421,7 +562,13 @@ private extension Popover { let y = self.layer.position.y + (anchorPoint.y - lastAnchor.y) * self.layer.bounds.size.height self.layer.position = CGPoint(x: x, y: y) - frame.size.height += self.arrowSize.height + switch self.popoverType { + case .up, .down, .auto: + frame.size.height += self.arrowSize.height + case .left, .right: + frame.size.width += self.arrowSize.height + } + self.frame = frame } @@ -446,6 +593,8 @@ private extension Popover { self.contentView.frame.origin.y = 0.0 case .down, .auto: self.contentView.frame.origin.y = self.arrowSize.height + case .left, .right: + self.contentView.frame.origin.x = 0 } self.addSubview(self.contentView) self.containerView.addSubview(self) diff --git a/Example/Popover/Base.lproj/Main.storyboard b/Example/Popover/Base.lproj/Main.storyboard index d8a2556..48f2720 100644 --- a/Example/Popover/Base.lproj/Main.storyboard +++ b/Example/Popover/Base.lproj/Main.storyboard @@ -1,12 +1,11 @@ - + - - + @@ -33,7 +32,7 @@ + + + + + + + + + @@ -71,8 +97,10 @@ + + @@ -85,7 +113,7 @@ - + diff --git a/Example/Popover/ViewController.swift b/Example/Popover/ViewController.swift index 0095db9..a5ec28c 100644 --- a/Example/Popover/ViewController.swift +++ b/Example/Popover/ViewController.swift @@ -14,7 +14,9 @@ class ViewController: UIViewController { @IBOutlet weak var rightBarButton: UIBarButtonItem! @IBOutlet weak var leftBottomButton: UIButton! @IBOutlet weak var rightButtomButton: UIButton! - + @IBOutlet weak var leftTopButton: UIButton! + @IBOutlet weak var rightCenterButton: UIButton! + fileprivate var texts = ["Edit", "Delete", "Report"] fileprivate var popover: Popover! @@ -62,6 +64,22 @@ class ViewController: UIViewController { } self.popover.show(tableView, fromView: self.rightButtomButton) } + + @IBAction func tappedLeftTopButton(_ sender: UIButton) { + let width = self.view.frame.width / 4 + let aView = UIView(frame: CGRect(x: 0, y: 0, width: width, height: width)) + let options: [PopoverOption] = [.type(.right), .showBlackOverlay(false)] + let popover = Popover(options: options, showHandler: nil, dismissHandler: nil) + popover.show(aView, fromView: self.leftTopButton) + } + + @IBAction func tappedRightCenterButton(_ sender: UIButton) { + let width = self.view.frame.width / 4 + let aView = UIView(frame: CGRect(x: 0, y: 0, width: width, height: width)) + let options: [PopoverOption] = [.type(.left), .showBlackOverlay(false)] + let popover = Popover(options: options, showHandler: nil, dismissHandler: nil) + popover.show(aView, fromView: self.rightCenterButton) + } } extension ViewController: UITableViewDelegate {