iOS开发 UIView设置顶部边框与左上右上圆角后圆角颜色不显示求助
问题根因
roundCorners方法中调用的UIBezierPath.stroke()逻辑无效。stroke()必须在有活跃图形上下文(例如draw(_ rect:)方法内)的场景下才会生效,在普通扩展方法中调用不会把边框渲染到视图上,这段描边代码等于未执行。- 单独添加的顶部边框是矩形CALayer,本身为直角形状,给视图layer添加圆角mask后,顶部边框CALayer在圆角位置的部分会被mask直接裁剪掉,自然无法显示圆角处的边框。
- 如果视图使用自动布局,调用方法时视图的
bounds还未完成最终计算,会导致圆角路径、边框frame和实际视图尺寸不匹配,也会触发显示异常。
修复方案
直接用同一个带圆角的UIBezierPath同时处理圆角mask和顶部边框渲染,不要分开执行mask设置和矩形边框添加逻辑。修正后的扩展代码如下:
extension UIView { /// 同时设置指定圆角 + 单边边框(支持圆角位置边框正常显示) /// - Parameters: /// - corners: 要添加圆角的位置 /// - radius: 圆角半径 /// - borderSide: 要添加的边框位置 /// - borderColor: 边框颜色 /// - borderThickness: 边框粗细 func setRoundedCornersWithSingleBorder(corners: UIRectCorner, radius: CGFloat, borderSide: ViewSide, borderColor: UIColor, borderThickness: CGFloat) { // 1. 设置圆角mask let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) let maskLayer = CAShapeLayer() maskLayer.frame = bounds maskLayer.path = maskPath.cgPath layer.mask = maskLayer // 2. 移除旧边框避免重复添加 removeBorder(toSide: borderSide) // 3. 生成和圆角路径匹配的边框层 let borderLayer = CAShapeLayer() borderLayer.name = borderSide.rawValue borderLayer.frame = bounds borderLayer.fillColor = UIColor.clear.cgColor borderLayer.strokeColor = borderColor.cgColor borderLayer.lineWidth = borderThickness // 裁剪边框仅保留需要的侧边 switch borderSide { case .Top: borderLayer.path = maskPath.cgPath // 裁剪掉下半部分路径,仅保留顶部+圆角区域的边框 let borderMask = CALayer() borderMask.backgroundColor = UIColor.black.cgColor borderMask.frame = CGRect(x: 0, y: 0, width: bounds.width, height: borderThickness + radius) borderLayer.mask = borderMask case .Left, .Right, .Bottom: // 其他侧边边框逻辑可参照上方写法扩展 break } layer.addSublayer(borderLayer) } enum ViewSide: String { case Left = "Left", Right = "Right", Top = "Top", Bottom = "Bottom" } func removeBorder(toSide side: ViewSide) { guard let sublayers = layer.sublayers else { return } sublayers.filter({ $0.name == side.rawValue }).first?.removeFromSuperlayer() } // 自动布局场景下需在布局更新时重新调用上述方法,保证路径和视图尺寸匹配 override open func layoutSubviews() { super.layoutSubviews() } }
使用示例
// 保证在视图布局完成后调用,例如viewDidAppear、layoutSubviews生命周期内 targetView.setRoundedCornersWithSingleBorder( corners: [.topLeft, .topRight], radius: 10, borderSide: .Top, borderColor: .white, borderThickness: 1 )
内容的提问来源于stack exchange,提问作者VURAL Çetin
相关产品推荐
相关产品推荐

