透明UIButton标题
如何从按钮背景中减去标题文字的形状?透明UIButton标题
我创建一个自定义的UIButton类。目前添加边框和文字颜色的代码看起来就像这样
layer.borderWidth = 2.0
layer.borderColor = buttonColor.CGColor
layer.cornerRadius = (CGFloat(bounds.height) + paddingVertical * 2.0)/2.0
setTitleColor(buttonColor, forState: UIControlState.Normal)
任何关于如何从背景减去按钮标题形状的建议。我是否需要将所有这些渲染为图像,还是有更好的选择?
我已经写了一些代码对你来说,(可在GitHub上https://github.com/purrrminator/AKStencilButton)我叫AKStencilButton的UIButton子类:
#import "AKStencilButton.h"
#import <QuartzCore/QuartzCore.h>
@interface AKStencilButton()
{
UIColor * _buttonColor;
}
@end
@implementation AKStencilButton
-(id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]){
[self setupDefaults];
}
return self;
}
-(instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]){
[self setupDefaults];
}
return self;
}
-(void)setupDefaults
{
self.backgroundColor = [UIColor redColor];
self.layer.cornerRadius = 4;
self.clipsToBounds = YES;
}
-(void)layoutSubviews
{
[super layoutSubviews];
[self refreshMask];
}
-(void)setTitleColor:(UIColor *)color forState:(UIControlState)state
{
[super setTitleColor:[UIColor clearColor] forState:state];
}
-(void)refreshMask
{
self.titleLabel.backgroundColor = [UIColor clearColor];
[self setTitleColor:[UIColor clearColor] forState:UIControlStateNormal];
NSString * text = self.titleLabel.text;
CGSize buttonSize = self.bounds.size;
UIFont * font = self.titleLabel.font;
NSDictionary* attribs = @{NSFontAttributeName: self.titleLabel.font};
CGSize textSize = [text sizeWithAttributes:attribs];
UIGraphicsBeginImageContextWithOptions(buttonSize, NO, [[UIScreen mainScreen] scale]);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGPoint center = CGPointMake(buttonSize.width/2-textSize.width/2, buttonSize.height/2-textSize.height/2);
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, buttonSize.width, buttonSize.height)];
CGContextAddPath(ctx, path.CGPath);
CGContextFillPath(ctx);
CGContextSetBlendMode(ctx, kCGBlendModeDestinationOut);
[text drawAtPoint:center withAttributes:@{NSFontAttributeName:font}];
UIImage* viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CALayer *maskLayer = [CALayer layer];
maskLayer.contents = (__bridge id)(viewImage.CGImage);
maskLayer.frame = self.bounds;
self.layer.mask = maskLayer;
}
@end
它看起来像这样(对不起,彩虹):
也许回答这个问题,但答案应该在[so]上发布,而不仅仅在github上。 – 2014-12-13 17:32:27
好的。现在看起来好吗? – 2014-12-13 17:39:03
谢谢。看看现在在Swift中重写这个... – Bernd 2014-12-13 21:57:39
我向UIView添加了以下方法来解决这个问题:
-(void)maskSubviews:(NSArray*)subviews {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
CGContextFillRect(context, self.bounds);
CGContextSetBlendMode(context, kCGBlendModeDestinationOut);
for (UIView *view in subviews) {
CGPoint origin = [view convertPoint:CGPointZero toView:self];
CGContextTranslateCTM(context, origin.x, origin.y);
[view.layer renderInContext:context];
CGContextTranslateCTM(context, -origin.x, -origin.y);
}
UIImage* mask = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.maskView = [[UIImageView alloc] initWithImage:mask];
}
只需用你想遮盖的视图来调用它。例如:
[button maskSubviews: @[button.titleLabel, button.imageView]]
我将@ purrrminator的解决方案转换为Swift 3,只是主要的方法。
func clearTextButton(button: UIButton, title: NSString, color: UIColor) {
button.backgroundColor = color
button.titleLabel?.backgroundColor = UIColor.clear()
button.setTitleColor(UIColor.clear(), for: .normal)
button.setTitle(title as String, for: [])
let buttonSize: CGSize = button.bounds.size
let font: UIFont = button.titleLabel!.font
let attribs: [String : AnyObject] = [NSFontAttributeName: button.titleLabel!.font]
let textSize: CGSize = title.size(attributes: attribs)
UIGraphicsBeginImageContextWithOptions(buttonSize, false, UIScreen.main().scale)
let ctx: CGContext = UIGraphicsGetCurrentContext()!
ctx.setFillColor(UIColor.white().cgColor)
let center: CGPoint = CGPoint(x: buttonSize.width/2 - textSize.width/2, y: buttonSize.height/2 - textSize.height/2)
let path: UIBezierPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: buttonSize.width, height: buttonSize.height))
ctx.addPath(path.cgPath)
ctx.fillPath()
ctx.setBlendMode(.destinationOut)
title.draw(at: center, withAttributes: [NSFontAttributeName: font])
let viewImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
let maskLayer: CALayer = CALayer()
maskLayer.contents = ((viewImage.cgImage) as! AnyObject)
maskLayer.frame = button.bounds
button.layer.mask = maskLayer
}
太多的强制解包选项。在所有这些情况下,条件解包将会更好:如果让font = button.titleLabel?.font,{...},如果让ctx = UIGraphicsGetCurrentContext(){...}等等。 – GK100 2016-08-09 17:15:36
@ GK100确实,只是一个快速和肮脏的变化。一些变量是有保证的,比如titleLabel,因为我之前设置了标题。 – 2016-08-11 00:17:42
如果你有这样的图像,这可以很容易地实现。 – Mrunal 2014-12-13 11:05:24
我正在寻找一个编程解决方案 – Bernd 2014-12-13 11:15:43
这里的一点点改变可能会帮助你:http://*.com/questions/23515100/ios-uibutton-with-transparent-title-on-white-background – Mrunal 2014-12-13 11:18:50