iOS自定义按钮--NVUIGradientButton
https://github.com/nverinaud/NVUIGradientButton
// // NVUIGradientButton.h // // Created by Nicolas Verinaud on 20/06/12. // Copyright (c) 2012 nverinaud.com. All rights reserved. // #import <UIKit/UIKit.h> typedef enum { NVUIGradientButtonStyleDefault = 1, NVUIGradientButtonStyleBlackOpaque, NVUIGradientButtonStyleBlackTranslucent } NVUIGradientButtonStyle; @interface NVUIGradientButton : UIControl @property (nonatomic, assign) NVUIGradientButtonStyle style; @property (nonatomic) CGFloat cornerRadius; // Default to 10.0 @property (nonatomic) CGFloat borderWidth; // Default to 2.0 @property (strong, nonatomic) UIColor *tintColor; // Default to gray @property (strong, nonatomic) UIColor *highlightedTintColor; // Default to nice blue @property (strong, nonatomic) UIColor *borderColor; // Default to darkGray @property (strong, nonatomic) UIColor *highlightedBorderColor; // Default to white @property (strong, nonatomic) UIColor *textColor; // Default to black @property (strong, nonatomic) UIColor *highlightedTextColor; // Default to white @property (strong, nonatomic) UIColor *textShadowColor; // Default to clear @property (strong, nonatomic) UIColor *highlightedTextShadowColor; // Default to darkGrey @property (copy, nonatomic) NSString *text; @property (copy, nonatomic) NSString *highlightedText; // Default to text @property (copy, nonatomic) NSString *disabledText; // Default to text @property (strong, nonatomic, readonly) UILabel *titleLabel; @property (nonatomic, getter = isGradientEnabled) BOOL gradientEnabled; // Default to YES, set to NO to draw flat color @property (nonatomic, strong) UIImage *rightAccessoryImage; @property (nonatomic, strong) UIImage *rightHighlightedAccessoryImage; // Designated initializer - (id)initWithFrame:(CGRect)frame style:(NVUIGradientButtonStyle)style cornerRadius:(CGFloat)cornerRadius borderWidth:(CGFloat)borderWidth andText:(NSString *)text; // Convenient initializers - (id)initWithFrame:(CGRect)frame cornerRadius:(CGFloat)cornerRadius borderWidth:(CGFloat)borderWidth andText:(NSString *)text; - (id)initWithFrame:(CGRect)frame style:(NVUIGradientButtonStyle)style; // Convenience for configuration depending on states - (void)setTintColor:(UIColor *)tintColor forState:(UIControlState)state; - (void)setBorderColor:(UIColor *)borderColor forState:(UIControlState)state; - (void)setTextColor:(UIColor *)textColor forState:(UIControlState)state; - (void)setTextShadowColor:(UIColor *)textShadowColor forState:(UIControlState)state; - (void)setText:(NSString *)text forState:(UIControlState)state; - (void)setRightAccessoryImage:(UIImage *)rightAccessoryImage forState:(UIControlState)state; @end // // NVUIGradientButton.m // // Created by Nicolas Verinaud on 20/06/12. // Copyright (c) 2012 nverinaud.com. All rights reserved. // #import "NVUIGradientButton.h" @interface NVUIGradientButton () - (void)performDefaultInit; - (void)updateAccordingToStyle; - (BOOL)isHighlightedOrSelected; - (UIColor *)tintColorAccordingToCurrentState; - (UIColor *)borderColorAccordingToCurrentState; - (UIColor *)textColorAccordingToCurrentState; - (UIColor *)textShadowColorAccordingToCurrentState; - (NSString *)textAccordingToCurrentState; - (UIImage *)rightAccessoryImageAccordingToCurrentState; - (CGGradientRef)newGradientAccordingToCurrentState; @property (strong, nonatomic, readwrite) UILabel *titleLabel; @end @implementation NVUIGradientButton #pragma mark - Memory Management - (void)dealloc { [_tintColor release]; [_highlightedTintColor release]; [_borderColor release]; [_highlightedBorderColor release]; [_textColor release]; [_highlightedTextColor release]; [_textShadowColor release]; [_highlightedTextShadowColor release]; [_text release]; [_highlightedText release]; [_disabledText release]; [_titleLabel release]; [_rightAccessoryImage release]; [_rightHighlightedAccessoryImage release]; [super dealloc]; } #pragma mark - Creation #define NVUIGradientButtonDefaultCorderRadius 10.0 #define NVUIGradientButtonDefaultBorderWidth 2.0 - (void)performDefaultInit { // Defaults _highlightedText = [_text copy]; _disabledText = [_text copy]; // Label _titleLabel = [[UILabel alloc] init]; _titleLabel.textAlignment = UITextAlignmentCenter; _titleLabel.lineBreakMode = UILineBreakModeMiddleTruncation; _titleLabel.numberOfLines = 0; _titleLabel.font = [UIFont boldSystemFontOfSize:15.0]; _titleLabel.minimumFontSize = 12.0; _titleLabel.shadowOffset = CGSizeMake(0, -1); _gradientEnabled = YES; self.opaque = NO; self.backgroundColor = [UIColor clearColor]; } - (void)updateAccordingToStyle { switch (_style) { case NVUIGradientButtonStyleBlackOpaque: { self.tintColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; self.highlightedTintColor = [UIColor colorWithRed:(CGFloat)3/255 green:(CGFloat)112/255 blue:(CGFloat)236/255 alpha:1]; self.borderColor = [UIColor whiteColor]; self.highlightedBorderColor = [UIColor whiteColor]; self.textColor = [UIColor whiteColor]; self.highlightedTextColor = [UIColor whiteColor]; self.textShadowColor = [UIColor clearColor]; self.highlightedTextShadowColor = [UIColor clearColor]; break; } case NVUIGradientButtonStyleBlackTranslucent: { self.tintColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7]; self.highlightedTintColor = [UIColor colorWithRed:(CGFloat)3/255 green:(CGFloat)112/255 blue:(CGFloat)236/255 alpha:0.7]; self.borderColor = [UIColor whiteColor]; self.highlightedBorderColor = [UIColor whiteColor]; self.textColor = [UIColor whiteColor]; self.highlightedTextColor = [UIColor whiteColor]; self.textShadowColor = [UIColor clearColor]; self.highlightedTextShadowColor = [UIColor clearColor]; break; } case NVUIGradientButtonStyleDefault: { CGFloat gray = 220.0/255.0; self.tintColor = [UIColor colorWithRed:gray green:gray blue:gray alpha:1]; self.highlightedTintColor = [UIColor colorWithRed:0 green:(CGFloat)157/255 blue:1 alpha:1]; self.borderColor = [UIColor darkGrayColor]; self.highlightedBorderColor = [UIColor whiteColor]; self.textColor = [UIColor blackColor]; self.highlightedTextColor = [UIColor whiteColor]; self.textShadowColor = [UIColor clearColor]; self.highlightedTextShadowColor = [UIColor darkGrayColor]; break; } } } #pragma mark Designated initializer - (id)initWithFrame:(CGRect)frame style:(NVUIGradientButtonStyle)style cornerRadius:(CGFloat)cornerRadius borderWidth:(CGFloat)borderWidth andText:(NSString *)text { self = [super initWithFrame:frame]; if (self) { _cornerRadius = cornerRadius; _borderWidth = borderWidth; _text = [text copy]; [self performDefaultInit]; self.style = style; } return self; } #pragma mark Convenient initializers - (id)initWithFrame:(CGRect)frame cornerRadius:(CGFloat)cornerRadius borderWidth:(CGFloat)borderWidth andText:(NSString *)text { return [self initWithFrame:frame style:NVUIGradientButtonStyleDefault cornerRadius:cornerRadius borderWidth:borderWidth andText:text]; } - (id)initWithFrame:(CGRect)frame style:(NVUIGradientButtonStyle)style { return [self initWithFrame:frame style:style cornerRadius:NVUIGradientButtonDefaultCorderRadius borderWidth:NVUIGradientButtonDefaultBorderWidth andText:nil]; } #pragma mark Overriden initializers - (id)initWithFrame:(CGRect)frame { return [self initWithFrame:frame style:NVUIGradientButtonStyleDefault cornerRadius:NVUIGradientButtonDefaultCorderRadius borderWidth:NVUIGradientButtonDefaultBorderWidth andText:nil]; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { _cornerRadius = NVUIGradientButtonDefaultCorderRadius; _borderWidth = NVUIGradientButtonDefaultBorderWidth; [self performDefaultInit]; self.style = NVUIGradientButtonStyleDefault; } return self; } #pragma mark - Setters - (void)setStyle:(NVUIGradientButtonStyle)style { if (style != _style) { _style = style; [self updateAccordingToStyle]; } } - (void)setTintColor:(UIColor *)tintColor { if (tintColor != _tintColor) { [_tintColor release]; _tintColor = [tintColor retain]; if (self.state == UIControlStateNormal) [self setNeedsDisplay]; } } - (void)setHighlightedTintColor:(UIColor *)highlightedTintColor { if (highlightedTintColor != _highlightedTintColor) { [_highlightedTintColor release]; _highlightedTintColor = [highlightedTintColor retain]; if ([self isHighlightedOrSelected]) [self setNeedsDisplay]; } } - (void)setBorderColor:(UIColor *)borderColor { if (borderColor != _borderColor) { [_borderColor release]; _borderColor = [borderColor retain]; if (self.state == UIControlStateNormal) [self setNeedsDisplay]; } } - (void)setHighlightedBorderColor:(UIColor *)highlightedBorderColor { if (highlightedBorderColor != _highlightedBorderColor) { [_highlightedBorderColor release]; _highlightedBorderColor = [highlightedBorderColor retain]; if ([self isHighlightedOrSelected]) [self setNeedsDisplay]; } } - (void)setTextColor:(UIColor *)textColor { if (textColor != _textColor) { [_textColor release]; _textColor = [textColor retain]; if (self.state == UIControlStateNormal) [self setNeedsDisplay]; } } - (void)setHighlightedTextColor:(UIColor *)highlightedTextColor { if (highlightedTextColor != _highlightedTextColor) { [_highlightedTextColor release]; _highlightedTextColor = [highlightedTextColor retain]; if ([self isHighlightedOrSelected]) [self setNeedsDisplay]; } } - (void)setTextShadowColor:(UIColor *)textShadowColor { if (textShadowColor != _textShadowColor) { [_textShadowColor release]; _textShadowColor = [textShadowColor retain]; if (self.state == UIControlStateNormal) [self setNeedsDisplay]; } } - (void)setHighlightedTextShadowColor:(UIColor *)highlightedTextShadowColor { if (highlightedTextShadowColor != _highlightedTextShadowColor) { [_highlightedTextShadowColor release]; _highlightedTextShadowColor = [highlightedTextShadowColor retain]; if ([self isHighlightedOrSelected]) [self setNeedsDisplay]; } } - (void)setText:(NSString *)text { if (![text isEqualToString:_text]) { [_text release]; _text = [text copy]; if (self.state == UIControlStateNormal) [self setNeedsDisplay]; } } - (void)setHighlightedText:(NSString *)highlightedText { if (![highlightedText isEqualToString:_highlightedText]) { [_highlightedText release]; _highlightedText = [highlightedText copy]; if ([self isHighlightedOrSelected]) [self setNeedsDisplay]; } } - (void)setDisabledText:(NSString *)disabledText { if (![disabledText isEqualToString:_disabledText]) { [_disabledText release]; _disabledText = [disabledText copy]; if (self.state & UIControlStateDisabled) [self setNeedsDisplay]; } } - (void)setRightAccessoryImage:(UIImage *)rightAccessoryImage { if (rightAccessoryImage != _rightAccessoryImage) { [_rightAccessoryImage release]; _rightAccessoryImage = [rightAccessoryImage retain]; if (self.state == UIControlStateNormal) [self setNeedsDisplay]; } } - (void)setRightHighlightedAccessoryImage:(UIImage *)rightHighlightedAccessoryImage { if (rightHighlightedAccessoryImage != _rightHighlightedAccessoryImage) { [_rightHighlightedAccessoryImage release]; _rightHighlightedAccessoryImage = [rightHighlightedAccessoryImage retain]; if ([self isHighlightedOrSelected]) [self setNeedsDisplay]; } } #pragma mark - Convenience configuration for states - (BOOL)isHighlightedOrSelected { return (self.state & UIControlStateHighlighted || self.state & UIControlStateSelected); } - (void)setTintColor:(UIColor *)tintColor forState:(UIControlState)state { if (state == UIControlStateNormal) self.tintColor = tintColor; if (state & UIControlStateHighlighted || state & UIControlStateSelected) self.highlightedTintColor = tintColor; } - (void)setBorderColor:(UIColor *)borderColor forState:(UIControlState)state { if (state == UIControlStateNormal) self.borderColor = borderColor; if (state & UIControlStateHighlighted || state & UIControlStateSelected) self.highlightedBorderColor = borderColor; } - (void)setTextColor:(UIColor *)textColor forState:(UIControlState)state { if (state == UIControlStateNormal) self.textColor = textColor; if (state & UIControlStateHighlighted || state & UIControlStateSelected) self.highlightedTextColor = textColor; } - (void)setTextShadowColor:(UIColor *)textShadowColor forState:(UIControlState)state { if (state == UIControlStateNormal) self.textShadowColor = textShadowColor; if (state & UIControlStateHighlighted || state & UIControlStateSelected) self.highlightedTextShadowColor = textShadowColor; } - (void)setText:(NSString *)text forState:(UIControlState)state { if (state == UIControlStateNormal) self.text = text; if (state & UIControlStateDisabled) self.disabledText = text; if (state & UIControlStateHighlighted || state & UIControlStateSelected) self.highlightedText = text; } - (void)setRightAccessoryImage:(UIImage *)rightAccessoryImage forState:(UIControlState)state { if (state == UIControlStateNormal) self.rightAccessoryImage = rightAccessoryImage; if (state & UIControlStateHighlighted || state & UIControlStateSelected) self.rightHighlightedAccessoryImage = rightAccessoryImage; } - (UIColor *)tintColorAccordingToCurrentState { UIColor *tintColor = _tintColor; if([self isHighlightedOrSelected]) tintColor = _highlightedTintColor; return tintColor; } - (UIColor *)borderColorAccordingToCurrentState { UIColor *borderColor = _borderColor; if ([self isHighlightedOrSelected] && _highlightedBorderColor) borderColor = _highlightedBorderColor; return borderColor; } - (UIColor *)textColorAccordingToCurrentState { UIColor *textColor = _textColor; if ([self isHighlightedOrSelected] && _highlightedTextColor) textColor = _highlightedTextColor; if (!self.enabled) textColor = [textColor colorWithAlphaComponent:0.5]; return textColor; } - (UIColor *)textShadowColorAccordingToCurrentState { UIColor *textShadowColor = _textShadowColor; if ([self isHighlightedOrSelected] && _highlightedTextShadowColor) textShadowColor = _highlightedTextShadowColor; return textShadowColor; } - (NSString *)textAccordingToCurrentState { NSString *text = _text; if (!self.enabled && _disabledText) text = _disabledText; else if ([self isHighlightedOrSelected] && _highlightedText) text = _highlightedText; return text; } - (UIImage *)rightAccessoryImageAccordingToCurrentState { UIImage *image = _rightAccessoryImage; if ([self isHighlightedOrSelected] && _rightHighlightedAccessoryImage) image = _rightHighlightedAccessoryImage; return image; } #pragma mark - Gradient - (CGGradientRef)newGradientAccordingToCurrentState { CGGradientRef gradient = NULL; // Compute the colors of the gradient UIColor *middleColor = [self tintColorAccordingToCurrentState]; CGFloat red = 0, green = 0, blue = 0, alpha = 0; if ([middleColor respondsToSelector:@selector(getRed:green:blue:alpha:)]) // iOS 5+ { [middleColor getRed:&red green:&green blue:&blue alpha:&alpha]; } else if (middleColor) { CGColorRef color = [middleColor CGColor]; const CGFloat *components = CGColorGetComponents(color); red = components[0]; green = components[1]; blue = components[2]; alpha = components[3]; } CGFloat offsetColor = 50.0f/255.0f; UIColor *topColor = [UIColor colorWithRed:fminf(1, red+offsetColor) green:fminf(1, green+offsetColor) blue:fminf(1, blue+offsetColor) alpha:alpha]; UIColor *bottomColor = [UIColor colorWithRed:fminf(1, red-offsetColor) green:fminf(1, green-offsetColor) blue:fminf(1, blue-offsetColor) alpha:alpha]; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); // Create an array of colors CFMutableArrayRef colors = CFArrayCreateMutable(NULL, 3, NULL); CFArrayAppendValue(colors, [topColor CGColor]); CFArrayAppendValue(colors, [middleColor CGColor]); CFArrayAppendValue(colors, [bottomColor CGColor]); // Create the gradient gradient = CGGradientCreateWithColors(colorSpace, colors, NULL); // Memory free CFRelease(colors); CGColorSpaceRelease(colorSpace); return gradient; } #pragma mark - Drawing #define DEFAULT_PADDING 4 - (void)drawRect:(CGRect)rect { // Setting Env CGContextRef ctx = UIGraphicsGetCurrentContext(); UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:_cornerRadius]; CGFloat padding = _borderWidth + DEFAULT_PADDING; UIColor *borderColor = [self borderColorAccordingToCurrentState]; UIColor *textColor = [self textColorAccordingToCurrentState]; UIColor *textShadowColor = [self textShadowColorAccordingToCurrentState]; NSString *text = [self textAccordingToCurrentState]; // Draw [path addClip]; // Draw background if (_gradientEnabled) { CGGradientRef gradient = [self newGradientAccordingToCurrentState]; CGFloat midX = CGRectGetMidX(self.bounds); CGFloat botY = CGRectGetMaxY(self.bounds); CGPoint startPoint = CGPointMake(midX, 0); CGPoint endPoint = CGPointMake(midX, botY); CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, 0); CGGradientRelease(gradient); } else { UIColor *tint = [self tintColorAccordingToCurrentState]; [tint set]; [path fill]; } // Draw right image UIImage *rightImage = [self rightAccessoryImageAccordingToCurrentState]; CGRect rightAccessoryRect = CGRectZero; if (rightImage) { CGFloat maxHeight = CGRectGetHeight(self.bounds) - padding*2; rightAccessoryRect.size.height = MIN(maxHeight, rightImage.size.height); rightAccessoryRect.size.width = rightAccessoryRect.size.height / rightImage.size.height * rightImage.size.width; rightAccessoryRect.origin.y = (CGRectGetHeight(self.bounds) - CGRectGetHeight(rightAccessoryRect)) / 2; rightAccessoryRect.origin.x = CGRectGetWidth(self.bounds) - CGRectGetWidth(rightAccessoryRect) - padding; [rightImage drawInRect:rightAccessoryRect]; } // Draw border if (_borderWidth > 0) { path.lineWidth = _borderWidth; [borderColor set]; [path stroke]; } // Draw text CGRect innerRect = self.bounds; innerRect = CGRectInset(innerRect, padding, padding); if (rightImage) innerRect.size.width = CGRectGetMinX(rightAccessoryRect); _titleLabel.textColor = textColor; _titleLabel.shadowColor = textShadowColor; _titleLabel.text = text; [textColor set]; [_titleLabel drawTextInRect:innerRect]; } #pragma mark - Touch Handling - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { self.highlighted = YES; [self setNeedsDisplay]; return [super beginTrackingWithTouch:touch withEvent:event]; } - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { self.highlighted = [self isTouchInside]; [self setNeedsDisplay]; return [super continueTrackingWithTouch:touch withEvent:event]; } - (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { [super endTrackingWithTouch:touch withEvent:event]; self.highlighted = NO; [self setNeedsDisplay]; } - (void)cancelTrackingWithEvent:(UIEvent *)event { [super cancelTrackingWithEvent:event]; self.highlighted = NO; [self setNeedsDisplay]; } #pragma mark - Accessibility - (BOOL)isAccessibilityElement { return YES; } - (NSString *)accessibilityLabel { return [self textAccordingToCurrentState]; } - (UIAccessibilityTraits)accessibilityTraits { UIAccessibilityTraits traits = UIAccessibilityTraitButton; if ([self isHighlightedOrSelected]) traits = traits >> UIAccessibilityTraitSelected; if (!self.enabled) traits = traits >> UIAccessibilityTraitNotEnabled; return traits; } - (NSString *)accessibilityHint { return [self textAccordingToCurrentState]; } @end