UIButton w/ gradient, rounded corners, border, and drop shadow(带有渐变、圆角、边框和阴影的 UIButton)
问题描述
网站上有一些类似的问题,但我正在寻找一些具体且略有不同的问题.
There are a few similar questions on the site, but I'm looking for something specific and slightly different.
我遵循这里给出的方向:http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/ 子类化 UIButton 以创建一个我可以指定的通用类渐变色,而不是尝试使用静态图像.
I followed the direction given here: http://www.cimgf.com/2010/01/28/fun-with-uibuttons-and-core-animation-layers/ to subclass UIButton in order to create a generic class that I can specify the gradient colors on, rather than trying to use a static image.
我遇到了一个问题,按钮层上的 setMasksToBounds 要么允许a) 阴影要显示,也可以让渐变层显示超出圆角或者B)渐变层剪辑到圆角,但不允许显示阴影
I ran into a problem where the setMasksToBounds on the button's layer would either allow A) the drop shadow to show, but also allow the gradient layer to show beyond the rounded corners OR B) the gradient layer to clip to the rounded corners, but not allow the drop shadow to show
我对该问题的解决方案似乎很笨拙,并且(尽管它有效)我想看看是否有人知道更好和/或更清洁的方法来完成同样的事情.这是我的代码:
My solution to the problem seemed clunky and (although it works) I wanted to see if anyone knew of a better and/or cleaner way to accomplish the same thing. Here's my code:
CSGradientButton.h
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(有趣的部分,无论如何)
CSGradient.m (the interesting parts, anyway)
#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: 方法来允许顶层和包装器"进行调整.
As you can see, I add a 'wrapper' layer that the gradient layer can safely mask to, while the top level CALayer of the button view can safely set masksToBounds = NO when the dropshadow is added. I add a setCornerRadius: method to allow both the top layer and the 'wrapper' to adjust.
所以与其做 [[myCustomButton layer] setCornerRadius:3.0f];
我只是说 [myCustomButton setCornerRadius:3.0f];
如你所见,它可能没有我希望的那么干净.
So rather than doing something like [[myCustomButton layer] setCornerRadius:3.0f];
I just say [myCustomButton setCornerRadius:3.0f];
As you can see, it's not maybe as clean as I'm hoping.
有没有更好的办法?
推荐答案
这就是我发现的具有圆角、渐变和阴影的按钮的方式.这个例子有一个特定的渐变,但显然可以用其他渐变代替.
This is the way I found to have a button with rounded corner, gradient, and drop shadow. This example has one particular gradient, but can obviously be replaced with other gradients.
@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
这篇关于带有渐变、圆角、边框和阴影的 UIButton的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:带有渐变、圆角、边框和阴影的 UIButton
- SetOnItemSelectedListener上的微调程序错误 2022-01-01
- GPS状态的广播接收器? 2022-01-01
- Xcode 7.3 中带有 UILabel 的 UIStackView 2022-01-01
- 网上有没有好的 UIScrollView 教程? 2022-01-01
- URL编码Swift iOS 2022-01-01
- 使用自动布局向 UIScrollView 添加动态大小的视图 2022-01-01
- UITextView 内容插图 2022-01-01
- 如何在 iPhone 模拟器中重置 NSUserDefaults 数据? 2022-01-01
- 在 Iphone SDK 的导航栏上添加多个按钮 2022-01-01
- 类似于 Mail.app 的 iPad 模态视图控制器? 2022-01-01