[英]How To Create in Swift a Circular Profile Picture or Rounded Corner Image with a border which does not leak?
Basing on the source code below: 基于以下源代码 :
@IBOutlet var myUIImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.makingRoundedImageProfileWithRoundedBorder()
}
private func makingRoundedImageProfileWithRoundedBorder() {
// Making a circular image profile.
// self.myUIImageView.layer.cornerRadius = self.myUIImageView.frame.size.width / 2
// Making a rounded image profile.
self.myUIImageView.layer.cornerRadius = 20.0
self.myUIImageView.clipsToBounds = true
// Adding a border to the image profile
self.myUIImageView.layer.borderWidth = 10.0
self.myUIImageView.layer.borderColor = UIColor.whiteColor().CGColor
}
Indeed I am able to render a circular or rounded UIImageView, but the problem is that if we add the border, the image leaks a bit. 事实上,我能够呈现圆形或圆形UIImageView,但问题是如果我们添加边框,图像会有点泄漏。 It's way worse with a circular UIImageView, it leaks whenever the border is bent, so LEAKS EVERYWHERE!
使用圆形UIImageView会更糟糕,只要边框弯曲,它就会泄漏,因此无论如何都会泄漏! You can find a screenshot of the result below:
您可以在下面找到结果的屏幕截图:
Any way to fix that in Swift? 有什么方法可以解决这个问题吗? Any sample code which answers to this question will be highly appreciated.
任何回答此问题的示例代码都将受到高度赞赏。
Note: as far as possible the solution has to be compatible with iOS 7 and 8+. 注意:解决方案必须尽可能与iOS 7和8+兼容。
First Solution 第一解决方案
Basing on the @Jesper Schläger suggestion 基于@JesperSchläger的建议
"If I may suggest a quick and dirty solution: “如果我可以建议一个快速而肮脏的解决方案:
Instead of adding a border to the image view, you could just add another white view below the image view. 您可以在图像视图下方添加另一个白色视图,而不是在图像视图中添加边框。 Make the view extend 10 points in either direction and give it a corner radius of 20.0.
使视图在任一方向上延伸10个点,并使其角半径为20.0。 Give the image view a corner radius of 10.0."
为图像视图指定角半径10.0。“
Please find the Swift implementation below: 请在下面找到Swift实现:
import UIKit
class ViewController: UIViewController {
@IBOutlet var myUIImageView: UIImageView!
@IBOutlet var myUIViewBackground: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Making a circular UIView: cornerRadius = self.myUIImageView.frame.size.width / 2
// Making a rounded UIView: cornerRadius = 10.0
self.roundingUIView(self.myUIImageView, cornerRadiusParam: 10)
self.roundingUIView(self.myUIViewBackground, cornerRadiusParam: 20)
}
private func roundingUIView(let aView: UIView!, let cornerRadiusParam: CGFloat!) {
aView.clipsToBounds = true
aView.layer.cornerRadius = cornerRadiusParam
}
}
Second Solution 二解决方案
Would be to set a circle mask over a CALayer. 将在CALayer上设置圆形蒙版。
Please find the Objective-C implementation of this second solution below: 请在下面找到第二个解决方案的Objective-C实现:
CALayer *maskedLayer = [CALayer layer];
[maskedLayer setFrame:CGRectMake(50, 50, 100, 100)];
[maskedLayer setBackgroundColor:[UIColor blackColor].CGColor];
UIBezierPath *maskingPath = [UIBezierPath bezierPath];
[maskingPath addArcWithCenter:maskedLayer.position
radius:40
startAngle:0
endAngle:360
clockwise:TRUE];
CAShapeLayer *maskingLayer = [CAShapeLayer layer];
[maskingLayer setPath:maskingPath.CGPath];
[maskedLayer setMask:maskingLayer];
[self.view.layer addSublayer:maskedLayer];
If you comment out from line UIBezierPath *maskingPath = [UIBezierPath bezierPath];
如果您从行
UIBezierPath *maskingPath = [UIBezierPath bezierPath];
through [maskedLayer setMask:maskingLayer];
通过
[maskedLayer setMask:maskingLayer];
you will see that the layer is a square. 你会看到这个图层是一个正方形。 However when these lines are not commented the layer is a circle.
但是,如果未对这些行进行注释,则该图层为圆形。
Note: I neither tested this second solution nor provided the Swift implementation, so feel free to test it and let me know if it works or not through the comment section below. 注意:我既没有测试第二个解决方案也没有提供Swift实现,所以请随意测试它,并通过下面的评论部分让我知道它是否有效。 Also feel free to edit this post adding the Swift implementation of this second solution.
也可以随意编辑这篇文章,添加第二个解决方案的Swift实现。
I worked on improving the code but it keeps crashing. 我致力于改进代码,但它一直在崩溃。 I'll work on it, but I appear to have got a (rough) version working:
我会继续努力,但我似乎有一个(粗略)版本工作:
Edit Updated with a slightly nicer version. 编辑更新了一个更好的版本。 I don't like the
init:coder
method but maybe that can factored out/improved 我不喜欢
init:coder
方法,但也许可以考虑因素或改进
class RoundedImageView: UIView {
var image: UIImage? {
didSet {
if let image = image {
self.frame = CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale)
}
}
}
var cornerRadius: CGFloat?
private class func frameForImage(image: UIImage) -> CGRect {
return CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale)
}
override func drawRect(rect: CGRect) {
if let image = self.image {
image.drawInRect(rect)
let cornerRadius = self.cornerRadius ?? rect.size.width/10
let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
UIColor.whiteColor().setStroke()
path.lineWidth = cornerRadius
path.stroke()
}
}
}
let image = UIImage(named: "big-teddy-bear.jpg")
let imageView = RoundedImageView()
imageView.image = image
Let me know if that's the sort of thing you're looking for. 让我知道你是否正在寻找那种东西。
A little explanation: 一点解释:
As I'm sure you've found, the "border" that iOS can apply isn't perfect, and shows the corners for some reason. 我相信你已经发现,iOS可以应用的“边界”并不完美,并且出于某种原因显示了角落。 I found a few other solutions but none seemed to work.
我找到了一些其他的解决方案,但似乎都没有。 The reason this is a subclass of
UIView
, and not UIImageView
, is that drawRect:
is not called for subclasses of UIImageView
. 这是
UIView
的子类而不是UIImageView
的原因是没有为UIImageView
子类调用drawRect:
UIImageView
I am not sure about the performance of this code, but it seems good from my (limited) testing 我不确定这段代码的性能,但从我的(有限的)测试看起来很好
Original code: 原始代码:
class RoundedImageView: UIView {
var image: UIImage? {
didSet {
if let image = image {
self.frame = CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale)
}
}
}
private class func frameForImage(image: UIImage) -> CGRect {
return CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale)
}
override func drawRect(rect: CGRect) {
if let image = self.image {
self.image?.drawInRect(rect)
let path = UIBezierPath(roundedRect: rect, cornerRadius: 50)
UIColor.whiteColor().setStroke()
path.lineWidth = 10
path.stroke()
}
}
}
let image = UIImage(named: "big-teddy-bear.jpg")
let imageView = RoundedImageView()
imageView.image = image
imageView.layer.cornerRadius = 50
imageView.clipsToBounds = true
If I may suggest a quick and dirty solution: 如果我建议一个快速而肮脏的解决方案:
Instead of adding a border to the image view, you could just add another white view below the image view. 您可以在图像视图下方添加另一个白色视图,而不是在图像视图中添加边框。 Make the view extend 10 points in either direction and give it a corner radius of 20.0.
使视图在任一方向上延伸10个点,并使其角半径为20.0。 Give the image view a corner radius of 10.0.
为图像视图指定角半径10.0。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.