Ответ 1
Вы можете попытаться использовать CAShapelayer
с круговой дорожкой в качестве маски для слоя вместо использования радиуса угла.
В качестве альтернативы вы можете поместить изображение в контейнер с границей и увеличить один/два пикселя.
Я рисую аватары с изображениями, просто применяя cornerRadius
к слою UIImageView
, а также добавляя границу через borderWith
и 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
Вы можете попытаться использовать CAShapelayer
с круговой дорожкой в качестве маски для слоя вместо использования радиуса угла.
В качестве альтернативы вы можете поместить изображение в контейнер с границей и увеличить один/два пикселя.
Как сказано в комментариях, вы можете добавить прозрачную рамку к изображению, чтобы все было нормально. Вот фрагмент кода для этого (категория для 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;
}
Решение OP излишне сложно. Более простое и чистое решение. Создайте UIView, клип к границам, маске, границе и угловому радиусу, как указано выше, а затем добавьте UIIamgeview в качестве поднабора этого UIView. UIIamgeview будет обрезано родительским представлением, и у вас не будет проблемы с кровотечением.
Моему UIButton
нужен округленный радиус угла, в результате которого были зубчатые края. Установка borderStyle
в .roundedRect
исправлена.
button.borderStyle = .roundedRect
button.layer.cornerRadius = 4
button.layer.borderWidth = 1
button.layer.borderColor = .red.cgColor
Попробуйте установить:
[self setClipToBounds:YES]
У меня была такая же проблема, и мне хотелось найти решение, которое будет хорошо работать с раскадрой. То, что я сделал, - это разместить изображение внутри представления, а затем установить как пользовательский класс, который контролирует поведение. Теперь я могу полностью контролировать дизайн с раскадровки.
Я разместил код на GitHub.
https://github.com/brennanMKE/CircleButton
Что он делает, это переопределить функцию drawRect в UIView для UIButton и обычного UIView, чтобы он мог работать со многими представлениями. Оболочка также используется для управления цветом и шириной границы. Я просто удостоверяюсь, что есть некоторый запас между обернутым представлением и супервидом и использовать разницу в качестве ширины границы. Цвет фона супервизора становится цветом границы. Теперь я могу быстро сделать эти изменения во многих сценах в раскадровке без индивидуального кодирования каждого экземпляра.
- (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;
}
}