创建具有圆形指定边框的 UIView
Create UIView with rounded specified borders
我想创建一个具有我指定的圆角边框的 UIView。例如,我想创建一个有 3 个边框的 UIView:左、上和右,右上角和左上角的边框应该是圆角的。
这让我创建可调整大小的边框视图(没有圆角):
open class ResizableViewBorder: UIView {
open override func layoutSubviews() {
super.layoutSubviews()
setNeedsDisplay()
}
open override func draw(_ rect: CGRect) {
let edges = ... get some UIRectEdges here
let lineWidth = 1
if edges.contains(.top) || edges.contains(.all) {
addBezierPath(paths: [
CGPoint(x: 0, y: 0 + lineWidth / 2),
CGPoint(x: self.bounds.width, y: 0 + lineWidth / 2)
])
}
if edges.contains(.bottom) || edges.contains(.all) {
addBezierPath(paths: [
CGPoint(x: 0, y: self.bounds.height - lineWidth / 2),
CGPoint(x: self.bounds.width, y: self.bounds.height - lineWidth / 2)
])
}
if (edges.contains(.left) || edges.contains(.all) || edges.contains(.right)) && CurrentDevice.isRightToLeftLanguage{
addBezierPath(paths: [
CGPoint(x: 0 + lineWidth / 2, y: 0),
CGPoint(x: 0 + lineWidth / 2, y: self.bounds.height)
])
}
if (edges.contains(.right) || edges.contains(.all) || edges.contains(.left)) && CurrentDevice.isRightToLeftLanguage{
addBezierPath(paths: [
CGPoint(x: self.bounds.width - lineWidth / 2, y: 0),
CGPoint(x: self.bounds.width - lineWidth / 2, y: self.bounds.height)
])
}
}
private func addBezierPath(paths: [CGPoint]) {
let lineWidth = 1
let borderColor = UIColor.black
let path = UIBezierPath()
path.lineWidth = lineWidth
borderColor.setStroke()
UIColor.blue.setFill()
var didAddedFirstLine = false
for singlePath in paths {
if !didAddedFirstLine {
didAddedFirstLine = true
path.move(to: singlePath)
} else {
path.addLine(to: singlePath)
}
}
path.stroke()
}
}
但是,我找不到将角半径添加到指定角的可靠方法。我有一个用曲线来做的 hacky 方法:
let path = UIBezierPath()
path.lineWidth = 2
path.move(to: CGPoint(x: fakeCornerRadius, y: 0))
path.addLine(to: CGPoint(x: frame.width - fakeCornerRadius, y: 0))
path.addQuadCurve(to: CGPoint(x: frame.width, y: fakeCornerRadius), controlPoint: CGPoint(x: frame.width, y: 0))
path.addLine(to: CGPoint(x: frame.width, y: frame.height - fakeCornerRadius))
path.stroke()
这给了我这个:
为什么四边形曲线的那条线这么粗?我更喜欢使用 UIBezierPaths 而不是 CALayers,因为 CALayers 对性能有巨大的影响...
你画曲线的代码有问题,不是曲线粗,而是直线细。它们很薄,因为它们轻拍在视野的边缘。所以你的线宽是 2 点,但其中一个点 在视图之外 。而且点不是像素,那么还有哪些像素需要填充呢?只有视图内。所以直线的可见线宽为1,只有曲线的可见线宽为2。
另一个问题是您可能正在计算机上的模拟器中查看此应用程序 运行ning。但是模拟器的像素和你电脑显示器的像素不匹配。这会导致大量绘图伪影。精确检查绘图到像素级别的方法是使用模拟器应用程序的屏幕截图图像工具,并在预览或类似文件中查看生成的全尺寸图像文件。或者 运行 在设备上并在那里拍摄屏幕截图图像。
为了证明这一点,我修改了您的代码以在原始 rect
的插入版本中运行(顺便说一下,这应该是您视图的 边界 ,不是它的框架):
let fakeCornerRadius : CGFloat = 20
let rect2 = self.bounds.insetBy(dx: 2, dy: 2)
let path = UIBezierPath()
path.lineWidth = 2
path.move(
to: CGPoint(x: rect2.minX + fakeCornerRadius, y: rect2.minY))
path.addLine(
to: CGPoint(x: rect2.maxX - fakeCornerRadius, y: rect2.minY))
path.addQuadCurve(
to: CGPoint(x: rect2.maxX, y: rect2.minY + fakeCornerRadius),
controlPoint: CGPoint(x: rect2.maxX, y: rect2.minY))
path.addLine(
to: CGPoint(x: rect2.maxX, y: rect2.maxY - fakeCornerRadius))
path.stroke()
从模拟器应用程序中截取屏幕截图,我得到了这个:
如您所见,这缺少屏幕截图的瑕疵。
我想创建一个具有我指定的圆角边框的 UIView。例如,我想创建一个有 3 个边框的 UIView:左、上和右,右上角和左上角的边框应该是圆角的。
这让我创建可调整大小的边框视图(没有圆角):
open class ResizableViewBorder: UIView {
open override func layoutSubviews() {
super.layoutSubviews()
setNeedsDisplay()
}
open override func draw(_ rect: CGRect) {
let edges = ... get some UIRectEdges here
let lineWidth = 1
if edges.contains(.top) || edges.contains(.all) {
addBezierPath(paths: [
CGPoint(x: 0, y: 0 + lineWidth / 2),
CGPoint(x: self.bounds.width, y: 0 + lineWidth / 2)
])
}
if edges.contains(.bottom) || edges.contains(.all) {
addBezierPath(paths: [
CGPoint(x: 0, y: self.bounds.height - lineWidth / 2),
CGPoint(x: self.bounds.width, y: self.bounds.height - lineWidth / 2)
])
}
if (edges.contains(.left) || edges.contains(.all) || edges.contains(.right)) && CurrentDevice.isRightToLeftLanguage{
addBezierPath(paths: [
CGPoint(x: 0 + lineWidth / 2, y: 0),
CGPoint(x: 0 + lineWidth / 2, y: self.bounds.height)
])
}
if (edges.contains(.right) || edges.contains(.all) || edges.contains(.left)) && CurrentDevice.isRightToLeftLanguage{
addBezierPath(paths: [
CGPoint(x: self.bounds.width - lineWidth / 2, y: 0),
CGPoint(x: self.bounds.width - lineWidth / 2, y: self.bounds.height)
])
}
}
private func addBezierPath(paths: [CGPoint]) {
let lineWidth = 1
let borderColor = UIColor.black
let path = UIBezierPath()
path.lineWidth = lineWidth
borderColor.setStroke()
UIColor.blue.setFill()
var didAddedFirstLine = false
for singlePath in paths {
if !didAddedFirstLine {
didAddedFirstLine = true
path.move(to: singlePath)
} else {
path.addLine(to: singlePath)
}
}
path.stroke()
}
}
但是,我找不到将角半径添加到指定角的可靠方法。我有一个用曲线来做的 hacky 方法:
let path = UIBezierPath()
path.lineWidth = 2
path.move(to: CGPoint(x: fakeCornerRadius, y: 0))
path.addLine(to: CGPoint(x: frame.width - fakeCornerRadius, y: 0))
path.addQuadCurve(to: CGPoint(x: frame.width, y: fakeCornerRadius), controlPoint: CGPoint(x: frame.width, y: 0))
path.addLine(to: CGPoint(x: frame.width, y: frame.height - fakeCornerRadius))
path.stroke()
这给了我这个:
为什么四边形曲线的那条线这么粗?我更喜欢使用 UIBezierPaths 而不是 CALayers,因为 CALayers 对性能有巨大的影响...
你画曲线的代码有问题,不是曲线粗,而是直线细。它们很薄,因为它们轻拍在视野的边缘。所以你的线宽是 2 点,但其中一个点 在视图之外 。而且点不是像素,那么还有哪些像素需要填充呢?只有视图内。所以直线的可见线宽为1,只有曲线的可见线宽为2。
另一个问题是您可能正在计算机上的模拟器中查看此应用程序 运行ning。但是模拟器的像素和你电脑显示器的像素不匹配。这会导致大量绘图伪影。精确检查绘图到像素级别的方法是使用模拟器应用程序的屏幕截图图像工具,并在预览或类似文件中查看生成的全尺寸图像文件。或者 运行 在设备上并在那里拍摄屏幕截图图像。
为了证明这一点,我修改了您的代码以在原始 rect
的插入版本中运行(顺便说一下,这应该是您视图的 边界 ,不是它的框架):
let fakeCornerRadius : CGFloat = 20
let rect2 = self.bounds.insetBy(dx: 2, dy: 2)
let path = UIBezierPath()
path.lineWidth = 2
path.move(
to: CGPoint(x: rect2.minX + fakeCornerRadius, y: rect2.minY))
path.addLine(
to: CGPoint(x: rect2.maxX - fakeCornerRadius, y: rect2.minY))
path.addQuadCurve(
to: CGPoint(x: rect2.maxX, y: rect2.minY + fakeCornerRadius),
controlPoint: CGPoint(x: rect2.maxX, y: rect2.minY))
path.addLine(
to: CGPoint(x: rect2.maxX, y: rect2.maxY - fakeCornerRadius))
path.stroke()
从模拟器应用程序中截取屏幕截图,我得到了这个:
如您所见,这缺少屏幕截图的瑕疵。