Ios 如何使用遮罩为圆形图像添加边框
这是我的尝试:Ios 如何使用遮罩为圆形图像添加边框,ios,swift,mask,cashapelayer,Ios,Swift,Mask,Cashapelayer,这是我的尝试: func round() { let width = bounds.width < bounds.height ? bounds.width : bounds.height let mask = CAShapeLayer() mask.path = UIBezierPath(ovalInRect: CGRectMake(bounds.midX - width / 2, bounds.midY - width / 2, width, width)).C
func round() {
let width = bounds.width < bounds.height ? bounds.width : bounds.height
let mask = CAShapeLayer()
mask.path = UIBezierPath(ovalInRect: CGRectMake(bounds.midX - width / 2, bounds.midY - width / 2, width, width)).CGPath
self.layer.mask = mask
// add border
let frameLayer = CAShapeLayer()
frameLayer.path = mask.path
frameLayer.lineWidth = 4.0
frameLayer.strokeColor = UIColor.whiteColor().CGColor
frameLayer.fillColor = nil
self.layer.addSublayer(frameLayer)
}
func round(){
设width=bounds.width
它在iphone 6模拟器上工作(故事板大小为4.7),但在5s和6+上看起来很奇怪:
这是自动布局问题吗?如果没有边框,自动布局工作正常。这是我第一次使用口罩,所以我不确定我所做的是否正确
round
函数在viewdilayoutsubviews
中调用
有什么想法吗?最简单的方法是操纵图像视图本身的
层
imageView.layer.cornerRadius = imageView.bounds.size.width / 2.0
imageView.layer.borderWidth = 2.0
imageView.layer.borderColor = UIColor.whiteColor.CGColor
imageView.layer.masksToBounds = true
您可以在viewDidLayoutSubviews
或layoutSubviews
中包含此项,以确保大小始终正确
注:也许这项技术会让你的圆圈面具过时;-)。根据经验,始终选择最简单的解决方案。例如,如果您有子类UIImageView
,您可以覆盖layoutSubviews
,以便它(a)更新掩码;(b) 删除任何旧边界;和(c)添加新边界。在Swift 3中:
import UIKit
@IBDesignable
class RoundedImageView: UIImageView {
/// saved rendition of border layer
private weak var borderLayer: CAShapeLayer?
override func layoutSubviews() {
super.layoutSubviews()
// create path
let width = min(bounds.width, bounds.height)
let path = UIBezierPath(arcCenter: CGPoint(x: bounds.midX, y: bounds.midY), radius: width / 2, startAngle: 0, endAngle: .pi * 2, clockwise: true)
// update mask and save for future reference
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
// create border layer
let frameLayer = CAShapeLayer()
frameLayer.path = path.cgPath
frameLayer.lineWidth = 32.0
frameLayer.strokeColor = UIColor.white.cgColor
frameLayer.fillColor = nil
// if we had previous border remove it, add new one, and save reference to new one
borderLayer?.removeFromSuperlayer()
layer.addSublayer(frameLayer)
borderLayer = frameLayer
}
}
这样,它可以响应布局的变化,但可以确保清除任何旧的边界
顺便说一下,如果您不是子类化UIImageView
,而是将此逻辑放在视图控制器中,那么您将覆盖UIView的viewWillLayoutSubviews
,而不是UIView的layoutSubviews
。但基本想法是一样的
--
顺便说一下,我将遮罩与此形状层结合使用,因为如果仅应用UIView
的圆角,可能会产生奇怪的瑕疵(请看圆形边框下部非常细的灰线):
如果使用贝塞尔路径方法,则不会产生此类瑕疵:
对于Swift 2.3示例,请参见。阅读viewDidLayoutSubviews
的描述,它告诉您何时调用该方法,并且它看起来并不适合您想要实现的目标。我的替代方法是什么?创建视图类的子类,存储对添加的路径和层的引用,当检测到尺寸变化时修改它们(使用layoutSubviews
),以后再使用它。你能给我举个例子吗?我是新手。我用过这个,但是自动布局有很多问题,所以你应该用这个来解决你的自动布局问题。我要添加imageView.layer.masksToBounds=true
。我用这个解决方案来处理cornerRadius,还设置了masktoBounds=true,但是我的图像在不同的屏幕上运行时需要调整大小,并且有很多问题,我无法解决它们,所以我说我应该尝试掩蔽。cornerRadius
方法是臭名昭著的,因为当你仔细观察角落时,会引入不需要的瑕疵。我建议修复UIBezierPath
方法(如上面评论中的A-Live建议的那样)。这是一个多么好的答案。这解决了我所有的问题。非常感谢。工作顺利,但我们不能用画法吗?哇。回答得很好。SA上有太多类似的问题没有解决这个问题。@NikhilManapure-是的,你可以在方法中手动屏蔽和渲染,但我们通常避免这样做,因为理论上我们会丢失苹果实现的任何优化/功能。此外,这是一种通用机制,您可以使用它,而不必考虑视图的类型或它可能具有的任何子视图。