带有渐变、圆角、边框和阴影的 UIButton
Posted
技术标签:
【中文标题】带有渐变、圆角、边框和阴影的 UIButton【英文标题】:UIButton w/ gradient, rounded corners, border, and drop shadow 【发布时间】:2011-05-11 21:54:30 【问题描述】:网站上有一些类似的问题,但我正在寻找一些具体且略有不同的问题。
我遵循这里给出的方向:http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/ 子类化 UIButton,以便创建一个我可以指定渐变颜色的通用类,而不是尝试使用静态图像。
我遇到了一个问题,按钮层上的 setMasksToBounds 要么允许 a) 阴影要显示,也可以让渐变层显示超出圆角 或者 B)渐变层剪辑到圆角,但不允许显示阴影
我对该问题的解决方案似乎很笨拙,并且(尽管它有效)我想看看是否有人知道更好和/或更清洁的方法来完成同样的事情。这是我的代码:
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(有趣的部分,无论如何)
#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
如您所见,我添加了一个“包装”层,渐变层可以安全地遮罩到该层,而按钮视图的*** CALayer 可以在添加阴影时安全地设置 maskToBounds = NO。我添加了一个 setCornerRadius: 方法来允许顶层和“包装器”进行调整。
所以与其做[[myCustomButton layer] setCornerRadius:3.0f];
之类的事情,不如说[myCustomButton setCornerRadius:3.0f];
如您所见,它可能没有我希望的那么干净。
有没有更好的办法?
【问题讨论】:
具有讽刺意味的是,这个问题最终可能与 ios 7 不太相关 :) 【参考方案1】:这是我发现有一个带有圆角、渐变和阴影的按钮的方式。这个例子有一个特定的渐变,但显然可以用其他渐变代替。
@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
【讨论】:
嗨 Ischult2 - 你能包含头文件,或者指定这个实现的超类是什么? 这是一个 UIButton 子类(从代码和主要问题来看)。我利用了这段代码,它运行良好。进行了一些修改以使按钮看起来更好。这应该被标记为答案 您的渐变位置有所帮助。你做这样的数学有什么原因吗?你能不能直接做...... 1*0.9 或 1*0.95 甚至只是 0.9 或 0.95 ?也许我错过了一些东西,如果你能解释为什么你的数学是这样的渐变位置。干杯 效果很好,但是渐变出现在按钮文本上。改为在 index:0 处插入图层就可以了:[self.layer insertSublayer:gradient atIndex:0];
我不知道的是:--- gradient.cornerRadius = 10;
【参考方案2】:
除了插入渐变层之外,您还可以覆盖方法+layerClass
以返回CAGradientLayer
类。按钮的层比那个类,你可以很容易地设置它的颜色等。
+ (Class)layerClass
return [CAGradientLayer class];
【讨论】:
【参考方案3】:我遇到了类似的问题,但是我没有使用渐变,而是使用了背景图像。我最终解决了它:
+ (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];
真正有趣的是,如果你有一个 clearColor 作为 shadowLayer.backgroundColor 只是没有绘制。
【讨论】:
以上是关于带有渐变、圆角、边框和阴影的 UIButton的主要内容,如果未能解决你的问题,请参考以下文章