guidelines - toolbar ios
iOS: Rectángulo redondeado con borde sangrado color (7)
Aquí hay una subclase de UIImageView
que resuelve este problema.
Como sugiere la respuesta aceptada , agrega un CAShapeLayer
redondeado que tiene un ancho de borde y un radio de esquina 1px más grande que "buscado". Su marco comienza en CGPoint(x: 1, y: 1)
y tiene una altura 2px mayor que la altura de la vista de la imagen. De esa manera, cubre el sangrado a través.
Solución Swift 3+
Subclase:
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)
}
}
Uso:
@IBOutlet weak var imageView: UIImageView!
[...]
imageView.layer.cornerRadius = 20
imageView.borderWidth = 2
imageView.borderColor = .lightGray
imageView.setUp()
Resultado:
Estoy dibujando imágenes de avatar redondas, simplemente aplicando cornerRadius
a una capa de UIImageView
, y también agregando un borde a través de borderWith
y borderColor
. Al igual que:
self.layer.masksToBounds = YES;
self.layer.cornerRadius = imageDimension / 2.f;
self.layer.borderWidth = 1.f;
self.layer.borderColor = borderColor.CGColor;
Eso funciona muy bien, excepto por este pequeño, pero notable sangrado de contenido fuera de la frontera, como este:
¿Hay una manera de simplemente comenzar el borde por unos pocos 1/10 puntos, o insertar el contenido más que el borde?
Solución
Gracias a FelixLam, se me ocurrió una buena solución y la dejaré aquí para el otro mundo:
@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
Como se dijo en los comentarios, puede agregar un borde transparente a la imagen para que esté bien. Aquí hay un fragmento de código para hacerlo (una categoría para 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;
}
Intenta configurar:
[self setClipToBounds:YES]
La solución de OP es innecesariamente complicada. Una solución más fácil y limpia. Cree un UIView, un clip a límites, una máscara, un borde y un radio de esquina como arriba y luego agregue un UIIamgeview como una subvista de ese UIView. La vista principal recortará el UIIamgeview y no tendrá el problema de sangrado.
Mi UIButton
necesitaba un radio de esquina redondeado que daba como resultado bordes irregulares. Estableciendo borderStyle
a .roundedRect
arregló.
button.borderStyle = .roundedRect
button.layer.cornerRadius = 4
button.layer.borderWidth = 1
button.layer.borderColor = .red.cgColor
Podría intentar usar un CAShapelayer
con una ruta circular como máscara para la Capa en lugar de usar el radio de la esquina.
Alternativamente, puede colocar la vista de imagen en un contenedor que tiene el borde y es uno / dos píxeles más grande.
Tuve el mismo problema y quería una solución que funcionara bien con un Storyboard. Lo que hice fue colocar mi imagen dentro de una vista y luego establecer ambas en una clase personalizada que controla el comportamiento. Ahora puedo controlar totalmente el diseño desde un Storyboard.
He puesto el código en GitHub.
https://github.com/brennanMKE/CircleButton
Lo que hace es anular la función drawRect en UIView tanto para UIButton como para UIView normal, de modo que pueda funcionar con muchas vistas. También se utiliza una vista de envoltura para controlar el ancho y el color del borde. Simplemente me aseguro de que haya un margen entre la vista envuelta y la vista de supervisión y use la diferencia como el ancho del borde. El color de fondo de la vista de supervisión se convierte en el color del borde. Ahora puedo hacer estos cambios rápidamente en muchas escenas en un Storyboard sin tener que codificar de forma personalizada cada instancia.
- (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;
}
}