radius corner color ios uibutton border gradient shadow

ios - corner - UIButton w/gradient, esquinas redondeadas, borde y sombra paralela



swift 4 button border color (3)

En lugar de insertar una capa de degradado, también puede anular el método +layerClass para devolver la clase CAGradientLayer . La capa del botón es diferente de esa clase, y puede establecer fácilmente sus colores, etc.

+ (Class)layerClass { return [CAGradientLayer class]; }

Hay algunas preguntas similares en el sitio, pero estoy buscando algo específico y ligeramente diferente.

Seguí la dirección dada aquí: http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/ subclase UIButton para crear una clase genérica que pueda especifique los colores degradados, en lugar de tratar de usar una imagen estática.

Me encontré con un problema donde setMasksToBounds en la capa del botón permitiría A) mostrar la sombra paralela, pero también permitir que la capa de degradado se muestre más allá de las esquinas redondeadas O B) la capa de degradado para recortar en las esquinas redondeadas, pero no permitir que la sombra paralela muestre

Mi solución al problema parecía torpe y (aunque funciona) quería ver si alguien sabía de una manera mejor y / o más limpia de lograr lo mismo. Aquí está mi código:

CSGradientButton.h

#import <UIKit/UIKit.h> @interface CSGradientButton : UIButton { UIColor *_highColor; UIColor *_lowColor; CAGradientLayer *gradientLayer; CALayer *wrapperLayer; CGColorRef _borderColor; } @property (nonatomic, retain) UIColor *_highColor; @property (nonatomic, retain) UIColor *_lowColor; @property (nonatomic) CGColorRef _borderColor; @property (nonatomic, retain) CALayer *wrapperLayer; @property (nonatomic, retain) CAGradientLayer *gradientLayer; - (void)setHighColor:(UIColor*)color; - (void)setLowColor:(UIColor*)color; - (void)setBorderColor:(CGColorRef)color; - (void)setCornerRadius:(float)radius; @end

CSGradient.m (las partes interesantes, de todos modos)

#import "CSGradientButton.h" @implementation CSGradientButton ... - (void)awakeFromNib { // Initialize the gradient wrapper layer wrapperLayer = [[CALayer alloc] init]; // Set its bounds to be the same of its parent [wrapperLayer setBounds:[self bounds]]; // Center the layer inside the parent layer [wrapperLayer setPosition: CGPointMake([self bounds].size.width/2, [self bounds].size.height/2)]; // Initialize the gradient layer gradientLayer = [[CAGradientLayer alloc] init]; // Set its bounds to be the same of its parent [gradientLayer setBounds:[self bounds]]; // Center the layer inside the parent layer [gradientLayer setPosition: CGPointMake([self bounds].size.width/2, [self bounds].size.height/2)]; // Insert the layer at position zero to make sure the // text of the button is not obscured [wrapperLayer insertSublayer:gradientLayer atIndex:0]; [[self layer] insertSublayer:wrapperLayer atIndex:0]; // Set the layer''s corner radius [[self layer] setCornerRadius:0.0f]; [wrapperLayer setCornerRadius:0.0f]; // Turn on masking [wrapperLayer setMasksToBounds:YES]; // Display a border around the button // with a 1.0 pixel width [[self layer] setBorderWidth:1.0f]; } - (void)drawRect:(CGRect)rect { if (_highColor && _lowColor) { // Set the colors for the gradient to the // two colors specified for high and low [gradientLayer setColors: [NSArray arrayWithObjects: (id)[_highColor CGColor], (id)[_lowColor CGColor], nil]]; } [super drawRect:rect]; } - (void)setCornerRadius:(float)radius { [[self layer] setCornerRadius:radius]; // and get the wrapper for the gradient layer too [wrapperLayer setCornerRadius:radius]; } - (void)setHighColor:(UIColor*)color { // Set the high color and repaint [self set_highColor:color]; [[self layer] setNeedsDisplay]; } - (void)setLowColor:(UIColor*)color { // Set the low color and repaint [self set_lowColor:color]; [[self layer] setNeedsDisplay]; } - (void)setBorderColor:(CGColorRef)color { [[self layer] setBorderColor:color]; [[self layer] setNeedsDisplay]; } @end

Como puede ver, agrego una capa ''envoltura'' a la que la capa de degradado puede enmascarar de forma segura, mientras que el nivel superior CALayer de la vista de botón puede establecer con seguridad masksToBounds = NO cuando se agrega la sombra de gotas. Agrego un método setCornerRadius: para permitir que tanto la capa superior como la ''envoltura'' se ajusten.

Entonces, en lugar de hacer algo como [[myCustomButton layer] setCornerRadius:3.0f]; Solo digo [myCustomButton setCornerRadius:3.0f]; Como puede ver, no es tan limpio como esperaba.

¿Hay una mejor manera?


Esta es la forma en que encuentro tener un botón con esquina redondeada, degradado y sombra paralela. Este ejemplo tiene un gradiente particular, pero obviamente puede ser reemplazado por otros gradientes.

@implementation CustomButton - (id)initWithFrame:(CGRect)frame { if((self = [super initWithFrame:frame])){ [self setupView]; } return self; } - (void)awakeFromNib { [self setupView]; } # pragma mark - main - (void)setupView { self.layer.cornerRadius = 10; self.layer.borderWidth = 1.0; self.layer.borderColor = [UIColor colorWithRed:167.0/255.0 green:140.0/255.0 blue:98.0/255.0 alpha:0.25].CGColor; self.layer.shadowColor = [UIColor blackColor].CGColor; self.layer.shadowRadius = 1; [self clearHighlightView]; CAGradientLayer *gradient = [CAGradientLayer layer]; gradient.frame = self.layer.bounds; gradient.cornerRadius = 10; gradient.colors = [NSArray arrayWithObjects: (id)[UIColor colorWithWhite:1.0f alpha:1.0f].CGColor, (id)[UIColor colorWithWhite:1.0f alpha:0.0f].CGColor, (id)[UIColor colorWithWhite:0.0f alpha:0.0f].CGColor, (id)[UIColor colorWithWhite:0.0f alpha:0.4f].CGColor, nil]; float height = gradient.frame.size.height; gradient.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:0.2*30/height], [NSNumber numberWithFloat:1.0-0.1*30/height], [NSNumber numberWithFloat:1.0f], nil]; [self.layer addSublayer:gradient];} - (void)highlightView { self.layer.shadowOffset = CGSizeMake(1.0f, 1.0f); self.layer.shadowOpacity = 0.25; } - (void)clearHighlightView { self.layer.shadowOffset = CGSizeMake(2.0f, 2.0f); self.layer.shadowOpacity = 0.5; } - (void)setHighlighted:(BOOL)highlighted { if (highlighted) { [self highlightView]; } else { [self clearHighlightView]; } [super setHighlighted:highlighted]; } @end


Tuve un problema similar, sin embargo, en lugar de un gradiente, tenía una imagen para el fondo. Lo solucioné al final usando:

+ (void) styleButton:(UIButton*)button { CALayer *shadowLayer = [CALayer new]; shadowLayer.frame = button.frame; shadowLayer.cornerRadius = 5; shadowLayer.backgroundColor = [UIColor whiteColor].CGColor; shadowLayer.opacity = 0.5; shadowLayer.shadowColor = [UIColor blackColor].CGColor; shadowLayer.shadowOpacity = 0.6; shadowLayer.shadowOffset = CGSizeMake(1,1); shadowLayer.shadowRadius = 3; button.layer.cornerRadius = 5; button.layer.masksToBounds = YES; UIView* parent = button.superview; [parent.layer insertSublayer:shadowLayer below:button.layer]; }

Lo realmente interesante es que si tienes clearColor, shadowLayer.backgroundColor simplemente no dibujó.