swift 在UIView中使用角半径的边框宽度问题

zdwk9cvp  于 2023-10-15  发布在  Swift
关注(0)|答案(1)|浏览(151)

我在Swift中尝试为带有圆角半径的UIView设置边框宽度时遇到了一个问题。下面是我的代码的简化版本:

class ViewController: UIViewController {
    
    @IBOutlet weak var borderView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Setting corner radius causes border width issue
        borderView.layer.cornerCurve = .continuous
        borderView.layer.cornerRadius = 20
        borderView.layer.borderColor = UIColor.black.cgColor
        borderView.layer.borderWidth = 0.5
    }
}

在这段代码中,我在borderView上设置了一个角半径,沿着设置边框颜色和宽度。但是,应用圆角半径时,边框宽度显示不正确。有趣的是,当没有设置拐角半径时,边框宽度会正确显示。
我试过直接使用borderView.layer.borderColor和borderView.layer.borderWidth。不幸的是,我的方法没有解决这个问题。
我在下面附上了一张图片来说明这个问题:Illustration of Border Width Issue
有没有人能提供见解或建议一种替代方法,以实现围绕具有拐角半径的UIView的一致边界宽度?值得注意的是,当没有设置圆角半径时,边框宽度会正确显示。

yvfmudvl

yvfmudvl1#

这是因为您试图绘制的线条不是整数像素宽。这看起来会有所不同,这取决于线条是否是像素对齐的。
在scale=3屏幕上(大概是您正在使用的屏幕),一个像素是1/3点,但您试图绘制一条1/2点宽的线。这只比一个像素大一点点。在图形的某些点上,对齐方式如下所示:

细的蓝色正方形表示像素,粗线表示您试图绘制的线的边界。正如你所看到的,线条的宽度完全覆盖了一个像素,加上旁边的一点像素。最终结果是绘制出被覆盖的像素线。

在另一点上,由于某种原因(可能是圆角矩形绘制代码的某些实现细节),线条的对齐方式有所不同。对齐方式如下所示:

它不会完全覆盖任何一行像素。它确实覆盖了两行像素中的“大部分”,所以这两行被绘制出来,也许其中一行填充了稍微浅一点的颜色,这取决于像素被覆盖的实际比例。

另请参阅这些相关问题:

如果你只想画一条1像素宽的线,就像上面第一篇文章建议的那样将宽度设置为1 / UIScreen.main.scale1 / UIScreen.main.scale的倍数似乎不受绘制圆角矩形所引起的对齐更改的影响。
还要注意的是,如果你自己手写绘图代码,写出所有的坐标,那么所有的直线都将以相同的方式对齐。

class SomeView: UIView {
    override func draw(_ rect: CGRect) {
        let path = UIBezierPath()
        path.move(to: .init(x: rect.minX + 20, y: rect.minY))
        path.addLine(to: .init(x: rect.maxX - 20, y: rect.minY))
        path.addArc(withCenter: .init(x: rect.maxX - 20, y: rect.minY + 20), radius: 20, startAngle: 3 * .pi / 2, endAngle: 0, clockwise: true)
        path.move(to: .init(x: rect.maxX, y: rect.minY + 20))
        path.addLine(to: .init(x: rect.maxX, y: rect.maxY - 20))
        path.addArc(withCenter: .init(x: rect.maxX - 20, y: rect.maxY - 20), radius: 20, startAngle: 0, endAngle: .pi / 2, clockwise: true)
        path.move(to: .init(x: rect.maxX - 20, y: rect.maxY))
        path.addLine(to: .init(x: rect.minX + 20, y: rect.maxY))
        path.addArc(withCenter: .init(x: rect.minX + 20, y: rect.maxY - 20), radius: 20, startAngle: .pi / 2, endAngle: .pi, clockwise: true)
        path.move(to: .init(x: rect.minX, y: rect.maxY - 20))
        path.addLine(to: .init(x: rect.minX, y: rect.minY + 20))
        path.addArc(withCenter: .init(x: rect.minX + 20, y: rect.minY + 20), radius: 20, startAngle: .pi, endAngle: 3 * .pi / 2, clockwise: true)
        path.lineWidth = 1 / 2
        UIColor.black.setStroke()
        path.stroke()
    }
}

请注意,这是一个开放路径,与CALayer为其边界绘制的闭合路径不同。此外,为层边界绘制的圆角与addArc添加的圆弧略有不同。也许这就是为什么像素在绘制弧线后会以不同的方式对齐。

相关问题