在多个 UIView 周围创建边框

Create border around multiple UIViews

我有一堆形状不规则的键盘,我想在它们周围放置单独的边框。每个键都是一个单独的 UIView,它们都包含在包装器键盘视图中。它们看起来像这样:

理想情况下,所有边框都应该看起来像左下角的红色边框(在预览中模拟),并且在必要时有圆角,但我认为获得正确的形状是一个好的开始。

最好的方法是什么?形状和面具?复杂的路径?看来我无论如何都需要 CALayers,但我是新手。

非常感谢任何建议。非常感谢!

杰克

我想通了!我最终使用 CAShapeLayersUIBezierPaths 在键盘周围画了一个边框;我用圆弧来模拟圆角:

func createBezier(key1Num: Int, key2Num: Int, key3Num: Int, key4Num: Int) {
    borderPath = UIBezierPath()

    let key1 = self.keys[key1Num].frame
    let key2 = self.keys[key2Num].frame
    let key3 = self.keys[key3Num].frame
    let key4 = self.keys[key4Num].frame
    let arcRadius = key1.height * 1/32

    let start = CGPoint(x: key1.origin.x, y: key1.origin.y)

    func bothEdgeNotesBlack() {
        borderPath.move(to: start)
        borderPath.addLine(to: CGPoint(x: start.x, y: key1.height * 31/32))
        borderPath.addArc(withCenter: CGPoint(x: start.x + arcRadius, y: key1.height * 31/32), radius: arcRadius, startAngle: leftAng, endAngle: bottomAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key2.origin.x, y: key1.height))
        borderPath.addLine(to: CGPoint(x: key2.origin.x, y: key2.height - arcRadius))
        borderPath.addArc(withCenter: CGPoint(x: key2.origin.x + arcRadius, y: key2.height - arcRadius), radius: arcRadius, startAngle: leftAng, endAngle: bottomAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key3.origin.x + key3.width - arcRadius, y: key2.height))
        borderPath.addArc(withCenter: CGPoint(x: key3.origin.x + key3.width - arcRadius, y: key2.height - arcRadius), radius: arcRadius, startAngle: bottomAng, endAngle: rightAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key3.origin.x + key3.width, y: key4.height))
        borderPath.addLine(to: CGPoint(x: key4.origin.x + key4.width - arcRadius, y: key4.height))
        borderPath.addArc(withCenter: CGPoint(x: key4.origin.x + key4.width - arcRadius, y: key4.height - arcRadius), radius: arcRadius, startAngle: bottomAng, endAngle: rightAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key4.origin.x + key4.width, y: key4.origin.y))
        borderPath.close()
    }

    func leftBlackrightWhite() {
        borderPath.move(to: start)
        borderPath.addLine(to: CGPoint(x: start.x, y: key1.height * 31/32))
        borderPath.addArc(withCenter: CGPoint(x: start.x + arcRadius, y: key1.height * 31/32), radius: arcRadius, startAngle: leftAng, endAngle: bottomAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key2.origin.x, y: key1.height))
        borderPath.addLine(to: CGPoint(x: key2.origin.x, y: key2.height - arcRadius))
        borderPath.addArc(withCenter: CGPoint(x: key2.origin.x + arcRadius, y: key2.height - arcRadius), radius: arcRadius, startAngle: leftAng, endAngle: bottomAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key4.origin.x + key4.width - arcRadius, y: key4.height))
        borderPath.addArc(withCenter: CGPoint(x: key4.origin.x + key4.width - arcRadius, y: key4.height - arcRadius), radius: arcRadius, startAngle: bottomAng, endAngle: rightAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key4.origin.x + key4.width, y: key4.origin.y))
        borderPath.close()
    }

    func leftWhiteRightBlack() {
        borderPath.move(to: start)
        borderPath.addLine(to: CGPoint(x: start.x, y: key1.height * 31/32))
        borderPath.addArc(withCenter: CGPoint(x: start.x + arcRadius, y: key1.height * 31/32), radius: arcRadius, startAngle: leftAng, endAngle: bottomAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key3.origin.x + key3.width - arcRadius, y: key3.height))
        borderPath.addArc(withCenter: CGPoint(x: key3.origin.x + key3.width - arcRadius, y: key3.height - arcRadius), radius: arcRadius, startAngle: bottomAng, endAngle: rightAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key3.origin.x + key3.width, y: key4.height))
        borderPath.addLine(to: CGPoint(x: key4.origin.x + key4.width - arcRadius, y: key4.height))
        borderPath.addArc(withCenter: CGPoint(x: key4.origin.x + key4.width - arcRadius, y: key4.height - arcRadius), radius: arcRadius, startAngle: bottomAng, endAngle: rightAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key4.origin.x + key4.width, y: key4.origin.y))
        borderPath.close()
    }

    func bothEdgeNotesWhite() {
        borderPath.move(to: start)
        borderPath.addLine(to: CGPoint(x: start.x, y: key1.height * 31/32))
        borderPath.addArc(withCenter: CGPoint(x: start.x + arcRadius, y: key1.height * 31/32), radius: arcRadius, startAngle: leftAng, endAngle: bottomAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key4.origin.x + key4.width - arcRadius, y: key4.height))
        borderPath.addArc(withCenter: CGPoint(x: key4.origin.x + key4.width - arcRadius, y: key4.height - arcRadius), radius: arcRadius, startAngle: bottomAng, endAngle: rightAng, clockwise: false)
        borderPath.addLine(to: CGPoint(x: key4.origin.x + key4.width, y: key4.origin.y))
        borderPath.close()
    }

    switch self.keys[key1Num].keyType {
    case 2, 5, 7, 10, 12: // 1st key is black
        switch self.keys[key4Num].keyType {
            case 2, 5, 7, 10, 12: // last key is black
            bothEdgeNotesBlack()
        case 1, 3, 4, 6, 8, 9, 11:
            leftBlackrightWhite() // last key is white
        default:
            ()
        }
    case 1, 3, 4, 6, 8, 9, 11: // 1st key is white
        switch self.keys[key4Num].keyType {
        case 2, 5, 7, 10, 12: // last key is black
            leftWhiteRightBlack()
        case 1, 3, 4, 6, 8, 9, 11: // last key is white
            bothEdgeNotesWhite()
        default:
            ()
        }
    default:
        ()
    }
}

func borderBezier(key1Num: Int, key2Num: Int, key3Num: Int, key4Num: Int) {
    self.createBezier(key1Num: key1Num, key2Num: key2Num, key3Num: key3Num, key4Num: key4Num)

    let borderLayer = CAShapeLayer()
    borderLayer.zPosition = 4
    borderLayer.path = self.borderPath.cgPath

    borderLayer.fillColor = UIColor.clear.cgColor
    borderLayer.strokeColor = UIColor.red.cgColor
    borderLayer.lineWidth = 3.0
    self.borderLayer = borderLayer
    self.layer.addSublayer(self.borderLayer)
}

下图是工作代码,不是模型:-)