如何在 Swift 中为弹出框及其箭头添加边框颜色?

问题描述 投票:0回答:4

我的应用程序中有以下弹出窗口:

但我希望它看起来像这个编辑后的图像(请注意,即使箭头也有边框):

现在这可能吗?我已经在

UIViewController
中尝试了以下内容:

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

但这对箭头不起作用。这件事还有转机吗

swift uiview calayer popover uipopoverpresentationcontroller
4个回答
5
投票

我花了一段时间,但终于解决了这个问题。它从一个通用的 UiPopoverPresentationController 开始。目前还没有什么特别的。

此控制器将自身隐藏在

viewWillAppear
viewDidAppear
之间。因此,当弹出框成形时,我采用了它自己的蒙版路径,并用它来制作带有笔划的子图层。

    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)
    }

结果看起来像这样。


1
投票

您是否尝试过将笔划设置为 UIBezierPath?在关闭 UIBezierPath 之前,您可以使用以下代码行来执行此操作:

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

这是我在 Playground 上实现的结果:

但是,我意识到我无法更改它的宽度,因此我为边框创建了另一个图层。

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)

游乐场结果:

我认为这应该有帮助,但如果没有关于如何实现形状的代码,我真的无法提出太多建议。您使用的是 UIBezierPath 还是 CGContext?


0
投票

您可以使用 ElegantPopover 来完成此操作。

var design = PSDesign()
design.borders = [PSBorder(filling: .pureColor(yourBorderColor), width: yourBorderWidth)]

// Corner radius of popover
design.cornerRadius = 15

// Customise the arrow as you like
let arrow = PSArrow(height: 30, base: 60, baseCornerRadius: 5, direction: .up)

let popoverController = ElegantPopoverController(contentView: yourContentView,
                                            design: design,
                                            arrow: arrow
                                            barButtonItem: barBtnItem)

present(popoverController, animated: true)

0
投票

我发现 Alexander-Langer 的答案非常有效,只是它产生了两个边框,其中一个位于弹出窗口的中间。我发现 viewWillLayoutSubviews 在设置过程中被多次调用,具有两种不同的视图大小,并且为较小的视图设置清晰的颜色会产生更整洁的结果。

    // View Will Layout Subviews
//---------------------------------------------------------------------------------------------------------------------------------------
override func viewWillLayoutSubviews() {
    // Add a colored border around popup
    guard let shapeLayer = view.superview?.superview?.mask?.layer as? CAShapeLayer else { return }
    
    // Found this is called alternately for two different borders and one is smaller than the final
    // Views are about 53 pixels bigger than desired guide size,
    var colr = UIColor.green.cgColor
    if view.bounds.height < (262.0+40.0) {
        colr = UIColor.clear.cgColor
    }
    print("🔲 Rolling view bounds \(view.bounds.height) < ? pref size \(262.0+40.0))")
    
    let borderLayer = CAShapeLayer()
    borderLayer.path = shapeLayer.path
    borderLayer.lineWidth = 4
    borderLayer.fillColor = UIColor.clear.cgColor
    borderLayer.frame = shapeLayer.bounds
    borderLayer.strokeColor = colr
    view.superview?.superview?.layer.addSublayer(borderLayer)
}

就我而言,“262”是我的首选高度,弹出视图将大 53 以容纳所有内容。我只是确保较小的视图比我喜欢的尺寸大 40 以内,并且较小的视图有一个清晰的边界。

此外,将视图背景设置为相同的边框颜色将填充按钮旁边的小三角形。

© www.soinside.com 2019 - 2024. All rights reserved.