19

我正在绘制圆形头像图片,只需应用于cornerRadiusaUIImageView的图层,并通过borderWithand添加边框borderColor。像这样:

self.layer.masksToBounds = YES;
self.layer.cornerRadius = imageDimension / 2.f;
self.layer.borderWidth = 1.f;
self.layer.borderColor = borderColor.CGColor;

效果很好,除了边界外内容的这种微小但明显的出血,如下所示:

蒙版和边框外的内容渗出

有没有办法只将边框扩大几个 1/10 点,或者将内容比边框插入更多?


解决方案

多亏了 FelixLam,我想出了一个很好的解决方案,并将其留给后世:

@interface MMRoundImageViewWithBorder : UIView

- (id)initWithImage:(UIImage *)image borderWidth:(CGFloat)borderWidth;

@property (strong, nonatomic) UIImageView *imageView;
@property (assign, nonatomic) CGFloat borderWidth;
@property (strong, nonatomic) UIColor *borderColor;

@end

@implementation MMRoundImageViewWithBorder

- (id)initWithImage:(UIImage *)image borderWidth:(CGFloat)borderWidth {
    if (self = [super init]) {
        self.borderWidth = borderWidth;
        self.borderColor = UIColor.whiteColor;

        self.imageView = [[UIImageView alloc] initWithImage:image];
        [self addSubview:self.imageView];

        self.imageView.layer.masksToBounds = YES;
        self.layer.masksToBounds = YES;
    }
    return self;
}

- (void)setBorderColor:(UIColor *)borderColor {
    _borderColor = borderColor;
    self.backgroundColor = borderColor;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    [self refreshDimensions];
}

- (void)refreshDimensions {
    self.layer.cornerRadius = CGRectGetWidth(self.bounds) / 2.f;

    self.imageView.frame = CGRectInset(self.bounds, _borderWidth, _borderWidth);
    self.imageView.layer.cornerRadius = CGRectGetWidth(self.imageView.bounds) / 2.f;
}

- (void)setBorderWidth:(CGFloat)borderWidth {
    _borderWidth = borderWidth;
    [self refreshDimensions];
}

- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];
    [self refreshDimensions];
}

@end
4

7 回答 7

14

您可以尝试使用CAShapelayer带有圆形路径的 a 作为图层的蒙版,而不是使用圆角半径。

或者,您可以将图像视图放置在具有边框且大一/两个像素的容器中。

于 2013-10-24T12:21:32.563 回答
1

正如评论中所说,您可以为图像添加透明边框,这样就可以了。这是一段代码(UIImageView 的一个类别):

+ (UIImage *)imageWithImage:(UIImage *)image withTransparentBorderOfWidth:(CGFloat)width {
    CGSize size = image.size;
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width + width * 2, size.height + width * 2), NO, 0.0);
    [image drawInRect:CGRectMake(width, width, size.width, size.height)];
    image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}
于 2013-10-24T12:27:11.237 回答
0

OP 的解决方案过于复杂。更简单、更清洁的解决方案。像上面一样创建一个 UIView、剪辑到边界、蒙版、边框和圆角半径,然后添加一个 UIIamgeview 作为该 UIView 的子视图。UIIamgeview 将被父视图裁剪,您不会遇到出血问题。

于 2014-09-09T02:25:41.827 回答
0

UIImageView这是解决此问题的子类。

正如公认的答案所暗示的那样,它添加了一个圆形CAShapeLayer,其边框宽度和角半径比“想要的”大 1px。它的框架从图像视图的高度开始,CGPoint(x: 1, y: 1)并且高度比图像视图的高度大 2px。这样,它就覆盖了渗漏。

斯威夫特 3+ 解决方案

子类:

class BorderedRoundedImageView: UIImageView {
    let borderLayer = CALayer()
    
    var borderWidth: CGFloat!
    var borderColor: UIColor!
    
    func setUp() {
        borderLayer.borderWidth = borderWidth + 1
        borderLayer.borderColor = borderColor.cgColor
        layer.addSublayer(borderLayer)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        borderLayer.cornerRadius = layer.cornerRadius + 1
        borderLayer.frame = CGRect(x: -1, y: -1, width: frame.width + 2, height: frame.height + 2)
    }
}

用法:

@IBOutlet weak var imageView: UIImageView!

[...]

imageView.layer.cornerRadius = 20
imageView.borderWidth = 2
imageView.borderColor = .lightGray
imageView.setUp()

结果:

结果截图

于 2018-09-06T13:25:39.023 回答
0

UIButton需要一个圆角半径,这会导致锯齿状边缘。设置borderStyle.roundedRect修复它。

button.borderStyle = .roundedRect
button.layer.cornerRadius = 4
button.layer.borderWidth = 1
button.layer.borderColor = .red.cgColor
于 2017-07-28T14:02:46.920 回答
-1

尝试设置:

[self setClipToBounds:YES]
于 2013-10-24T12:22:14.193 回答
-1

我遇到了同样的问题,想要一个可以很好地与 Storyboard 配合使用的解决方案。我所做的是将图像放在视图中,然后将两者都设置为控制行为的自定义类。我现在可以从 Storyboard 完全控制设计。

我已将代码放在 GitHub 上。

https://github.com/brennanMKE/CircleButton

它的作用是为 UIButton 和常规 UIView 覆盖 UIView 中的 drawRect 函数,以便它可以与许多视图一起使用。包装视图也用于控制边框颜色和宽度。我只是确保包装视图和超级视图之间有一些边距,并将差异用作边框宽度。超级视图的背景颜色成为边框颜色。现在,我可以在 Storyboard 的许多场景中快速进行这些更改,而无需对每个实例进行自定义编码。

- (void)drawRect:(CGRect)rect {
    // round view and superview with a border using the background color of the superview
    self.layer.cornerRadius = CGRectGetWidth(self.frame) / 2;
    self.layer.masksToBounds = YES;

    if ([self.superview isKindOfClass:[SSTCircleWrapperView class]]) {
        self.superview.layer.cornerRadius = CGRectGetWidth(self.superview.frame) / 2;
        self.superview.layer.masksToBounds = YES;
        self.superview.layer.borderColor = self.superview.backgroundColor.CGColor;
        self.superview.layer.borderWidth = (CGRectGetWidth(self.superview.frame) - CGRectGetWidth(self.frame)) / 2;
    }
}
于 2013-11-13T07:14:10.773 回答