带有部分边框的 UIView 边框

Posted

技术标签:

【中文标题】带有部分边框的 UIView 边框【英文标题】:UIView border with partial border 【发布时间】:2020-08-21 12:44:49 【问题描述】:

我有 UIView,我只需要绘制边框部分视图,我该如何使用 UIBezierPath

【问题讨论】:

看看这个***.com/questions/36836367/… 【参考方案1】:

如果你想使用UIBezierPath,你可以选择“傻”的方式:

画出视图的完整边框 通过在边框顶部绘制一个矩形来“覆盖”您不希望边框与视图的背景颜色一起存在的部分。
class MyView: UIView 
    override init(frame: CGRect) 
        super.init(frame: frame)
        commonInit()
    
    
    required init?(coder: NSCoder) 
        super.init(coder: coder)
        commonInit()
    
    
    private func commonInit() 
        layer.cornerRadius = 3
        backgroundColor = .white
        layer.masksToBounds = true
    
    
    override func draw(_ rect: CGRect) 
        let borderPath = UIBezierPath(roundedRect: bounds, cornerRadius: 3)
        borderPath.lineWidth = 7
        UIColor.gray.setStroke()
        borderPath.stroke()
        let covering = UIBezierPath(rect: CGRect(x: 20, y: -10, width: self.bounds.width - 40, height: 20))
        backgroundColor?.setFill()
        covering.fill()
    

输出:

除此之外,我想不出一个简单的方法来做到这一点。

但是,如果你可以使用CAShapeLayer...

您应该设置作为视图层的子层添加的CAShapeLayerstrokeEndstrokeStart 属性。

例子:

class MyView: UIView 
    override init(frame: CGRect) 
        super.init(frame: frame)
        commonInit()
    
    
    required init?(coder: NSCoder) 
        super.init(coder: coder)
        commonInit()
    
    
    private func commonInit() 
        layer.cornerRadius = 3
        let border = CAShapeLayer()
        // make sure this path coincides with the border of the view
        border.path = UIBezierPath(roundedRect: bounds, cornerRadius: 3).cgPath

        // you should tweak these numbers
        border.strokeStart = 0.3
        border.strokeEnd = 0.7

        border.strokeColor = UIColor.gray.cgColor
        border.lineWidth = 3
        border.fillColor = nil
        layer.addSublayer(border)
        backgroundColor = .white
    

输出:

【讨论】:

【参考方案2】:

我做了完全相同的事情,但做了一次动画,以模仿 ios 应用程序中的 android 材料文本字段设计和行为,这里是形状创建代码:

placeholderWidth 是顶部间隙的大小,leftInset 是从框架左角插入

class FloatingTextfieldBorderShapeCreator 
    
    var leftInset: CGFloat

    init(leftInset: CGFloat) 
        self.leftInset = leftInset
    

    func create(frame: CGRect, placeholderWidth: CGFloat) -> CGPath 
        let path = UIBezierPath()
        let arcRadius: CGFloat = 4.0
    
        //1. starting point top left
        let startingPoint = CGPoint(x: frame.minX + leftInset - 4, y: frame.minY)
        path.move(to: startingPoint)
    
        //2. top left arc
        let topLeftArcCenter = CGPoint(x: frame.minX + arcRadius, y: arcRadius)
        path.addArc(withCenter: topLeftArcCenter, radius: arcRadius, startAngle: 3*CGFloat.pi/2, endAngle: CGFloat.pi, clockwise: false)
    
        //3. left line
        let leftLineEndPoint = CGPoint(x: frame.minX, y: frame.height - arcRadius)
        path.addLine(to: leftLineEndPoint)
    
        //4. bottom left arc
        let bottomLeftArcCenter = CGPoint(x: frame.minX + arcRadius, y: frame.height - arcRadius)
        path.addArc(withCenter: bottomLeftArcCenter, radius: arcRadius, startAngle: CGFloat.pi, endAngle: CGFloat.pi/2, clockwise: false)
    
        //5. bottom line
        let bottomLineEndPoint = CGPoint(x: frame.width - arcRadius, y: frame.height)
        path.addLine(to: bottomLineEndPoint)
    
        //6. bottom right arc
        let bottomRightArcCenter = CGPoint(x: frame.width - arcRadius, y: frame.height - arcRadius)
        path.addArc(withCenter: bottomRightArcCenter, radius: arcRadius, startAngle: CGFloat.pi/2, endAngle: 0, clockwise: false)
    
        //7. right line
        let rightLineEndPoint = CGPoint(x: frame.width, y: frame.minY + arcRadius)
        path.addLine(to: rightLineEndPoint)
    
        //8. top right arc
        let topRightArcCenter = CGPoint(x: frame.width - arcRadius, y: frame.minY + arcRadius)
        path.addArc(withCenter: topRightArcCenter, radius: arcRadius, startAngle: 0, endAngle: -CGFloat.pi/2, clockwise: false)
    
        //9. top line
        let topLineEndPointX = startingPoint.x + placeholderWidth
        let topLineEndPoint = CGPoint(x: topLineEndPointX, y: frame.minY)
        path.addLine(to: topLineEndPoint)
    
        return path.cgPath
    

以及应用于绘图层的属性:

    borderLayer.frame = borderFrame
    borderLayer.fillColor = nil
    borderLayer.lineWidth = 1.0
    borderLayer.strokeColor = .lightGray

【讨论】:

以上是关于带有部分边框的 UIView 边框的主要内容,如果未能解决你的问题,请参考以下文章

UIView边框覆盖子视图?

如何快速在 UIView 上应用带有边框的尖角半径?

UIView 的圆顶角并添加边框

带有 alpha 通道部分的透明 PNG 显示带有丑陋的边框

如何绘制部分边框?

带有多个单元格边框的钱包样式 Swift