【发布时间】:2010-09-27 05:28:56
【问题描述】:
如何设置按钮的自定义背景颜色?
Interface Builder 似乎没有执行此操作的接口。
它只能以编程方式使用吗? 如果有,请提供一个例子吗?
【问题讨论】:
标签: iphone cocoa-touch
如何设置按钮的自定义背景颜色?
Interface Builder 似乎没有执行此操作的接口。
它只能以编程方式使用吗? 如果有,请提供一个例子吗?
【问题讨论】:
标签: iphone cocoa-touch
可能是我误解了您的问题,但以下内容对您不起作用?
【讨论】:
所以,我找到了一个使用类别的非常简单的解决方案。 (太简单了,我想我一定是在做一些 hacky,但我没有看到它!)
为 UIButton 定义一个类别(如果你不知道那是什么,总而言之:它是一种最小程度地“扩展”类的方法;即,向类添加方法但没有属性),并创建调用 UIButton 的超类 (UIControl) setBackgroundColor 方法的“setBackgroundColor”方法。
@implementation UIButton (coloredBackgroundButton)
-(void)setBackgroundColor:(UIColor *)backgroundColor {
[super setBackgroundColor:backgroundColor];
}
无论你在哪里使用UIButtons,只要你导入声明这个类别的头文件,在这种情况下,
#import "coloredBackgroundButton.h"
你可以对它们调用 setBackgroundColor。
【讨论】:
在@Denny1989 的基础上进一步构建我已经解决了在 viewDidLoad 中设置按钮时出现错误(无效上下文 0x0)的问题。按钮需要在它具有大小之前进行布局,因此在视图出现之前不能依赖它。此类别为 UIControlStateNormal 添加颜色。如果您的应用需要其他控件状态,您需要将它们添加到类别中。
// UIButton+ColoredBackground.h
#import <UIKit/UIKit.h>
@interface UIButton (ColoredBackground)
@property (nonatomic, retain) UIColor *buttonColorNormal;
@property (nonatomic, retain) NSNumber *madeBackgroundImages;
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state;
- (void)drawRect:(CGRect)rect;
- (void)awakeFromNib;
@end
和
// UIButton+ColoredBackground.m
#import "UIButton+ColoredBackground.h"
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>
#define kCornerRadius 8.0f
#define kStrokeColor [UIColor darkGrayColor]
#define kStrokeWidth 1.0f
@implementation UIButton (ColoredBackground)
static char UIB_ButtonColorNormal_KEY;
static char UIB_MadeBackgroundImages_KEY;
@dynamic buttonColorNormal;
-(void)setButtonColorNormal:(NSObject *)buttonColorNormal
{
objc_setAssociatedObject(self, &UIB_ButtonColorNormal_KEY, buttonColorNormal, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSObject*)buttonColorNormal
{
return (NSObject*)objc_getAssociatedObject(self, &UIB_ButtonColorNormal_KEY);
}
@dynamic madeBackgroundImages;
-(void)setMadeBackgroundImages:(NSObject *)madeBackgroundImages
{
objc_setAssociatedObject(self, &UIB_MadeBackgroundImages_KEY, madeBackgroundImages, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSObject*)madeBackgroundImages
{
return (NSObject*)objc_getAssociatedObject(self, &UIB_MadeBackgroundImages_KEY);
}
- (void)awakeFromNib {
[self setMadeBackgroundImages:[NSNumber numberWithBool:FALSE]];
[super awakeFromNib];
}
- (void)drawRect:(CGRect)rect {
// if background images were not created from color do so here
// if self.buttonColorNormal is not set behaves like normal button
if ((self.buttonColorNormal)&&(![[self madeBackgroundImages] boolValue])) {
[self setBackgroundColor:[self buttonColorNormal] forState:UIControlStateNormal];
[self setMadeBackgroundImages:[NSNumber numberWithBool:TRUE]];
}
[super drawRect:rect];
}
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state {
gcSize = CGSizeMake(2*kCornerRadius +1, self.bounds.size.height);
UIGraphicsBeginImageContext(gcSize);
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
UIColor *gradientStart = [UIColor colorWithRed:0.80 green:0.80 blue:0.80 alpha:0.2];
UIColor * gradientEnd = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5];
NSArray *colors = [NSArray arrayWithObjects:(id)gradientStart.CGColor, (id)gradientEnd.CGColor, nil];
CGFloat locations[2] = { 0.0f, 1.0f };
CGGradientRef _gradient = CGGradientCreateWithColors(rgb, (__bridge CFArrayRef)colors, locations);
CGColorSpaceRelease(rgb);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeOverlay);
CGContextDrawLinearGradient(UIGraphicsGetCurrentContext(), _gradient, CGPointMake(0.0, kStrokeWidth), CGPointMake(0.0, self.bounds.size.height-kStrokeWidth), 0);
UIBezierPath *outsideEdge = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.0, 0.0, gcSize.width, gcSize.height) cornerRadius:kCornerRadius];
[backgroundColor setFill];
[kStrokeColor setStroke];
outsideEdge.lineWidth = kStrokeWidth;
[outsideEdge stroke];
[outsideEdge fill];
CFRelease(_gradient);
// Create the background image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Set image as button's background image (stretchable) for the given state
[self setBackgroundImage:[image stretchableImageWithLeftCapWidth:kCornerRadius topCapHeight:0.0] forState:state];
// Ensure rounded button
self.clipsToBounds = YES;
self.layer.cornerRadius = kCornerRadius;
// add colored border
self.layer.borderColor = kStrokeColor.CGColor;
self.layer.borderWidth = kStrokeWidth;
}
@end
用法
- (void)viewDidLoad
{
[myButton setButtonColorNormal:[UIColor redColor]];
}
一定要自定义按钮类型,否则drawRect可能不会被调用。
【讨论】:
我稍微修改了@Patch 的代码版本。对我来说,问题是旧版本在从纵向模式切换到横向模式时会拉伸角半径有点脏。所以我让这个版本使用了 stretchableImageWithLeftCapWidth:topCapHeight 方法。
#import "UIButton+ColoredBackground.h"
#import <QuartzCore/QuartzCore.h>
#define kCornerRadius 8.0f
#define kStrokeColor [UIColor blackColor]
#define kStrokeWidth 1.0f
@implementation UIButton (ColoredBackground)
- (void)setBackgroundImageByColor:(UIColor *)backgroundColor forState:(UIControlState)state{
CGSize gcSize = CGSizeMake(2*kCornerRadius +1, self.bounds.size.height);
UIGraphicsBeginImageContext(gcSize);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeOverlay);
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
UIColor *gradientStart = [UIColor colorWithRed:0.80 green:0.80 blue:0.80 alpha:0.2];
UIColor * gradientEnd = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.2];
NSArray *colors = [NSArray arrayWithObjects:(id)gradientStart.CGColor, (id)gradientEnd.CGColor, nil];
CGFloat locations[2] = { 0.0f, 1.0f };
CGGradientRef _gradient = CGGradientCreateWithColors(rgb, (__bridge CFArrayRef)colors, locations);
CGColorSpaceRelease(rgb);
CGContextDrawLinearGradient(UIGraphicsGetCurrentContext(), _gradient, CGPointMake(0.0, kStrokeWidth), CGPointMake(0.0, self.bounds.size.height-kStrokeWidth), 0);
UIBezierPath *outsideEdge = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.0, 0.0, gcSize.width, gcSize.height) cornerRadius:kCornerRadius];
[backgroundColor setFill];
[kStrokeColor setStroke];
outsideEdge.lineWidth = kStrokeWidth;
[outsideEdge stroke];
[outsideEdge fill];
// Create the background image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Set image as button's background image (stretchable) for the given state
[self setBackgroundImage:[image stretchableImageWithLeftCapWidth:kCornerRadius topCapHeight:0.0] forState:state];
// Ensure rounded button
self.clipsToBounds = YES;
self.layer.cornerRadius = kCornerRadius;
}
@end
用法没有改变。现在边缘看起来更清晰了,我还添加了一个渐变来制作更多的塑料。但你也可以删除它。
【讨论】:
这是@user200212 解决方案的一个变体 (http://stackoverflow.com/a/8547424)。它使用UIBezierCurve 类来填充按钮并在其周围绘制一个 1px 的黑色边框:
UIButton+ColoredBackground.h
// UIButton+ColoredBackground.h
#import <UIKit/UIKit.h>
@interface UIButton (ColoredBackground)
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state;
+ (UIColor *) silverColor;
@end
UIButton+ColoredBackground.m
// UIButton+ColoredBackground.m
#import "UIButton+ColoredBackground.h"
#import <QuartzCore/QuartzCore.h>
@implementation UIButton (UIButton_ColoredBackground)
- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state{
CGSize gcSize = self.bounds.size;
UIGraphicsBeginImageContext(gcSize);
// Create a Bezier Path around the button, and fill it with the background color
UIBezierPath *outsideEdge = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:8.0f];
[backgroundColor setFill];
[[UIColor blackColor] setStroke];
outsideEdge.lineWidth = 1.0;
[outsideEdge fill];
[outsideEdge stroke];
// Create the background image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Set image as button's background image for the given state
[self setBackgroundImage:image forState:state];
// Ensure rounded button
self.clipsToBounds = YES;
self.layer.cornerRadius = 8.0;
}
@end
用法:
[myButton setBackgroundImageByColor:[UIColor greenColor] forState:UIControlStateNormal];
【讨论】:
看来,按钮颜色仍然是个问题。以下类别通过采用 UIColor 参数的实例方法完全以编程方式设置按钮的背景图像。无需创建按钮背景图像文件。它保留了基于 UIControlState 的按钮行为。它保留了圆角。
头文件UIButton+ColoredBackground.h
#import <UIKit/UIKit.h>
@interface UIButton (ColoredBackground)
- (void)setBackgroundImageByColor:(UIColor *)backgroundColor forState:(UIControlState)state;
@end
以及UIButton+ColoredBackground.m的内容
#import "UIButton+ColoredBackground.h"
#import <QuartzCore/QuartzCore.h>
@implementation UIButton (ColoredBackground)
- (void)setBackgroundImageByColor:(UIColor *)backgroundColor forState:(UIControlState)state{
// tcv - temporary colored view
UIView *tcv = [[UIView alloc] initWithFrame:self.frame];
[tcv setBackgroundColor:backgroundColor];
// set up a graphics context of button's size
CGSize gcSize = tcv.frame.size;
UIGraphicsBeginImageContext(gcSize);
// add tcv's layer to context
[tcv.layer renderInContext:UIGraphicsGetCurrentContext()];
// create background image now
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// set image as button's background image for the given state
[self setBackgroundImage:image forState:state];
UIGraphicsEndImageContext();
// ensure rounded button
self.clipsToBounds = YES;
self.layer.cornerRadius = 8.0;
[tcv release];
}
@end
在每个 UIButton 实例上都会调用新方法,例如:
[myButton setBackgroundImageByColor:[UIColor greenColor] forState:UIControlStateNormal];
【讨论】:
如果您不想使用图像,并且希望它看起来与圆角矩形样式完全一样,试试这个。只需在 UIButton 上放置一个 UIView,具有相同的框架和自动调整大小的掩码,将 alpha 设置为 0.3,并将背景设置为一种颜色。然后使用下面的 sn-p 将圆形边缘从彩色叠加视图中剪掉。此外,取消选中 UIView 上 IB 中的“用户交互已启用”复选框,以允许触摸事件向下级联到下方的 UIButton。
一个副作用是您的文本也会被着色。
#import <QuartzCore/QuartzCore.h>
colorizeOverlayView.layer.cornerRadius = 10.0f;
colorizeOverlayView.layer.masksToBounds = YES;
【讨论】:
我按如下方式创建按钮,如 uitableview 中的系统删除按钮
UIButton *h=[[UIButton alloc]init];
[[h layer] setCornerRadius:8.0f];
[[h layer] setMasksToBounds:YES];
[[h layer] setBorderWidth:1.0f];
CAGradientLayer *gradientLayer = [[CAGradientLayer alloc] init];
[gradientLayer setBounds:[h bounds]];
[gradientLayer setPosition:CGPointMake([h bounds].size.width/2, [h bounds].size.height/2)];
[gradientLayer setColors:[NSArray arrayWithObjects:
(id)[[UIColor darkGrayColor]CGColor],(id)[[UIColor blackColor] CGColor], nil]];
[[h layer] insertSublayer:gradientLayer atIndex:0];
释放所有对象并 导入 QuartzCore/QuartzCore.h 和 将此框架添加到您的项目中。
【讨论】:
这是我创建的一个免费应用程序,用于创建 UIGlassButton 图像。将按钮类型设置为自定义。 http://itunes.apple.com/us/app/uibutton-builder/id408204223?mt=8
【讨论】:
http://github.com/dermdaly/ButtonMaker
您可以使用此应用程序生成 UIbutton 图像...并可以将其设置为按钮的背景图像
【讨论】:
当我想要一个简单的“保存”按钮和一个不错的蓝色渐变背景时,Tim James 的解决方案(单段分段控件)对我有用。我只是在笔尖中创建了一个 2 段控件,根据需要设置第一个段,然后使用 [mySegmentedControl removeSegmentAtIndex:1 animated:NO] 以编程方式删除 -viewWillAppear 下的第二个段。 出于我的目的,需要为分段控件在笔尖中的第一个段启用(勾选)“瞬间”,而“选定”对于任何一个段都没有激活。 'Value Changed' 是分段控件的连接动作。
【讨论】:
要使按钮保持圆角,如何使用
view.layer.cornerRadius = 8;
这里描述
【讨论】:
我读到您的问题是要求(和我一样)一种程序化方式来设置按钮颜色。这是 UIKit 的明显遗漏,我无法让未记录的 UIGlassButton 工作。
我已经解决了这个问题,使用单个段 UISegmentedControl,它允许您设置 tintColor:
UISegmentedControl * btn = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:name]];
btn.momentary = YES;
btn.segmentedControlStyle = UISegmentedControlStyleBar;
btn.tintColor = color;
[btn addTarget:self action:@selector(action:) forControlEvents:UIControlEventValueChanged];
请注意momentary 和segmentedControlStyle 属性很重要,并且可以使用图像代替NSString * 名称。
如果您可以使用一组有限的固定图像,则带有端盖的可拉伸图像可以正常工作,但这不符合要求!例如,
buttonImage = [[UIImage imageNamed:@"button.png"] stretchableImageWithLeftCapWidth:26 topCapHeight:16];
【讨论】:
我通过在 Fireworks 中创建自己的按钮解决了这个问题。我用我想要的填充颜色和边框颜色画了一个大约我想要的大小的圆角矩形。修剪画布,并保存为 PNG。在 XCode 中,将文件添加到 Resources 文件夹。您可以在 Interface Builder 中使用自定义按钮并将图像指定为该 PNG。它会根据需要调整它的大小,将文本放在顶部等。如果您必须从原始大小调整它的大小,拐角的曲线可能会扭曲。
【讨论】:
当您单击按钮并进入检查器时,他说要更改“视图”背景颜色时,keremk 是对的。这会将小角更改为您选择的任何颜色。
【讨论】:
在按钮属性面板中将按钮类型设置为“自定义”。这将为您提供一个方形按钮,其中包含您为背景选择的任何颜色。
如果您想要一个看起来更像传统按钮但颜色不同的按钮,您需要进入某种图像编辑软件并创建它(我使用 Photoshop 来制作自定义按钮)。
【讨论】:
为圆角矩形按钮设置视图的背景颜色不会改变按钮的背景颜色。尝试将按钮设为自定义按钮(检查器中的第一个下拉菜单),然后设置背景颜色。你会得到想要的效果:)
【讨论】:
button.layer.cornerRadius 以获得圆形按钮(并且您需要启用button.layer.masksToBounds 以及AFAIK)。这对我来说是最简单的解决方案。
我发现我需要使用可拉伸的图像来完成此操作。 Apple 的 UICatalog 示例有一个或多个以这种方式绘制的彩色按钮。您可以使用他们的模板图像并重新着色以适合您的按钮需求。
我不确定是否在 Interface Builder 中执行此操作,但我能够使用以下代码创建一个按钮并为其内容使用图像:
downloadButton = [[UIButton alloc] initWithFrame:CGRectMake(36, 212, 247, 37)];
downloadButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
downloadButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[downloadButton setTitle:NSLocalizedStringFromTable(@"Download", @"Localized", nil) forState:UIControlStateNormal];
[downloadButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[downloadButton setFont:[UIFont boldSystemFontOfSize:14.0]];
UIImage *newImage = [[UIImage imageNamed:@"greenButton.png"] stretchableImageWithLeftCapWidth:12.0f topCapHeight:0.0f];
[downloadButton setBackgroundImage:newImage forState:UIControlStateNormal];
[downloadButton addTarget:self action:@selector(downloadNewItem) forControlEvents:UIControlEventTouchDown];
downloadButton.backgroundColor = [UIColor clearColor];
[downloadDisplayView addSubview:downloadButton];
【讨论】: