You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建带指定圆角边框的可调整大小UIView?

实现带指定圆角和部分边框的UIView(基于UIBezierPath)

Hey there! I get exactly what you're trying to build— a UIView with only top, left, right borders, plus rounded top corners, and you want to stick with UIBezierPath for performance instead of messing with CALayers. Let's break this down step by step to fix that thick line issue and get the exact result you want.

核心思路

  • We'll manually draw a bezier path that only includes the three required borders and two rounded corners
  • The key fix for the thick line problem is adjusting the path's position to account for how UIBezierPath centers its stroke, so the line doesn't bleed outside the view bounds
  • This approach keeps performance lean since we're using the view's native drawing cycle instead of stacking extra CALayers

具体实现代码

Create a custom UIView subclass (I'll call it PartialRoundedBorderView) with configurable properties and proper path drawing:

import UIKit

class PartialRoundedBorderView: UIView {
    // Make these properties configurable for easy tweaks
    var borderColor: UIColor = .black {
        didSet { setNeedsDisplay() }
    }
    var borderWidth: CGFloat = 1.0 {
        didSet { setNeedsDisplay() }
    }
    var cornerRadius: CGFloat = 8.0 {
        didSet { setNeedsDisplay() }
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        // Critical adjustment: inset the rect by half the border width
        // This ensures the stroke stays entirely within the view bounds (no overflow)
        let adjustedRect = rect.insetBy(dx: borderWidth/2, dy: borderWidth/2)
        
        let path = UIBezierPath()
        
        // Start at the bottom-left corner (end of left border)
        path.move(to: CGPoint(x: adjustedRect.minX, y: adjustedRect.maxY))
        
        // Draw left border up to the start of the top-left rounded corner
        path.addLine(to: CGPoint(x: adjustedRect.minX, y: adjustedRect.minY + cornerRadius))
        
        // Add top-left rounded corner arc
        path.addArc(withCenter: CGPoint(x: adjustedRect.minX + cornerRadius, y: adjustedRect.minY + cornerRadius),
                    radius: cornerRadius,
                    startAngle: .pi,
                    endAngle: .pi * 3/2,
                    clockwise: true)
        
        // Draw top border across to the start of the top-right rounded corner
        path.addLine(to: CGPoint(x: adjustedRect.maxX - cornerRadius, y: adjustedRect.minY))
        
        // Add top-right rounded corner arc
        path.addArc(withCenter: CGPoint(x: adjustedRect.maxX - cornerRadius, y: adjustedRect.minY + cornerRadius),
                    radius: cornerRadius,
                    startAngle: .pi * 3/2,
                    endAngle: 0,
                    clockwise: true)
        
        // Draw right border down to the bottom-right corner
        path.addLine(to: CGPoint(x: adjustedRect.maxX, y: adjustedRect.maxY))
        
        // Set stroke properties and draw the path
        borderColor.setStroke()
        path.lineWidth = borderWidth
        path.stroke()
    }
}

关键细节解释

  • Border inset adjustment: The adjustedRect line fixes the thick stroke issue. UIBezierPath draws strokes centered on the path line—without this inset, half the border width would lie outside the view, making it look thicker than intended.
  • Continuous path flow: We draw the path in a single continuous loop (bottom-left → top-left corner → top edge → top-right corner → bottom-right) to avoid gaps or disjointed lines.
  • Auto-redraw on changes: The didSet observers trigger setNeedsDisplay() whenever you tweak border color, width, or corner radius, so the view updates automatically.

性能优势

Using draw(_ rect:) with UIBezierPath is lightweight and efficient. It integrates directly with the view's native rendering cycle, so the system handles optimizations like clipping and redraws only when necessary. This is far more performant than adding multiple CALayers (like separate border layers and corner masks) especially if you're using multiple instances of this view.

使用示例

You can use this view programmatically or set it as the custom class for a view in Storyboard:

// Example setup in a ViewController
let customBorderView = PartialRoundedBorderView(frame: CGRect(x: 50, y: 100, width: 250, height: 180))
customBorderView.borderColor = .systemBlue
customBorderView.borderWidth = 2.0
customBorderView.cornerRadius = 12.0
customBorderView.backgroundColor = .systemGray5
view.addSubview(customBorderView)

This will give you exactly the view you want: only top, left, right borders, rounded top corners, clean stroke width, and great performance.

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:11:07