简体   繁体   English

如何在Swift中创建圆形轮廓图像或圆角图像,边框不会泄漏?

[英]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: 您可以在下面找到结果的屏幕截图:

UIImageView呈现

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.

相关问题 如何在 iOS Swift 中将圆形个人资料图片图像(来自 url 字符串)设置为 UIBarButton 项目 - How to set rounded profile picture image(from url string) to UIBarButton item in iOS Swift iOS快速创建舍入的个人资料图片,例如Twitter,Instagram, - ios swift create rounded profile image like twitter, instagram, 带有边框的UIImageView和带有图像的圆角从边框边缘弹出 - UIImageView with border and rounded corner with image pops out from the border edges 如何创建带边框的圆形图像(UIGraphics)? - How to create a circular image with border (UIGraphics)? 带有圆角的UITableView边框 - UITableView border with rounded corner 如何在Swift 4的UIView中创建带有圆角的渐变边框 - How to create Gradient border with rounded corners at UIView in Swift 4 如何在创建圆角时添加到边框UITextField Swift - How to add with to border UITextField Swift when when create Rounded corners UITextField 圆角 - swift - UITextField rounded corner - swift 如何快速从图像创建循环加载器 - How to create a circular loader from an image in swift 如何将UIButton放置在另一个UIImageView上,该UIImageView是圆形的配置文件图像? - How to place a UIButton on another UIImageView which is a circular profile image?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM