Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a border color on a popover and its arrow in Swift?

I have the following popover in my app:

enter image description here

But I want it to look like this edited image (note that even the arrow has a border):

enter image description here

Is this possible nowadays? I already tried the following inside the UIViewController:

self.view.layer.borderColor = UIColor.white.cgColor
self.view.layer.borderWidth = 2

But that doesn't work for the arrow. Is there any turn around on this?

like image 539
ThiagoAM Avatar asked Nov 01 '18 06:11

ThiagoAM


2 Answers

It took me a while, but finally I was able to solve this problem. It begins with a common UiPopoverPresentationController. Nothing special about it yet.

This Controller masks itself somewhere between viewWillAppear and viewDidAppear. So I took the path of its own mask when the popover was shaped and used this to make a sublayer with a stroke.

    override func viewWillLayoutSubviews() {
        guard let shapeLayer = view.superview?.superview?.mask?.layer as? CAShapeLayer else { return }
        let borderLayer = CAShapeLayer()
        borderLayer.path = shapeLayer.path
        borderLayer.lineWidth = 4
        borderLayer.strokeColor = borderColor.cgColor
        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.frame = shapeLayer.bounds
        view.superview?.superview?.layer.addSublayer(borderLayer)
    }

The result looks like this.

Result looks like this

like image 91
Alexander Langer Avatar answered Sep 26 '22 22:09

Alexander Langer


Have you tried setting the stroke to the UIBezierPath instead? You can do so with the following lines of code before you close your UIBezierPath:

Color.purple.setStroke()
bezierPath.stroke()

Here's the result I manage to achieve on Playground:

enter image description here

However, I realized that I couldn't change the width of it so instead, I created another layer just for the border instead.

let borderLayer = CAShapeLayer()
borderLayer.frame = self.bounds
borderLayer.path = bezierPath.cgPath
borderLayer.lineWidth = 6.0
borderLayer.strokeColor = UIColor.black.cgColor
borderLayer.fillColor = UIColor.clear.cgColor
self.layer.insertSublayer(borderLayer, at: 0)

Playground result:

enter image description here

I think this should help but I can't really suggest much without the code on how the shape is achieved. Are you using UIBezierPath or CGContext?

like image 41
Li Sim Avatar answered Sep 22 '22 22:09

Li Sim