From 66125d92ee1785abb2c50d26aef872001c4e7456 Mon Sep 17 00:00:00 2001 From: Peter Gammelgaard Date: Mon, 18 May 2015 14:25:45 +0200 Subject: [PATCH 1/6] Fixed a problem with selected title color for segment --- NYSegmentedControl/NYSegmentedControl.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/NYSegmentedControl/NYSegmentedControl.m b/NYSegmentedControl/NYSegmentedControl.m index c003213..2d08c9e 100644 --- a/NYSegmentedControl/NYSegmentedControl.m +++ b/NYSegmentedControl/NYSegmentedControl.m @@ -263,7 +263,6 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated: options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ previousSegment.titleLabel.font = self.titleFont; - previousSegment.titleLabel.textColor = self.titleTextColor; previousSegment.titleLabel.maskFrame = CGRectZero; } completion:nil]; @@ -273,7 +272,6 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated: options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ selectedSegment.titleLabel.font = self.selectedTitleFont; - selectedSegment.titleLabel.textColor = self.selectedTitleTextColor; if (self.drawsSegmentIndicatorGradientBackground) { //selectedSegment.titleLabel.shadowColor = [UIColor darkGrayColor]; From cda41c6020ea96a492780a9c809854b6e2483212 Mon Sep 17 00:00:00 2001 From: Peter Gammelgaard Date: Tue, 29 Sep 2015 11:40:24 +0200 Subject: [PATCH 2/6] Changed implementation of drawRect: for the label This is done to avoid a visual glitch when the selected title color is in a lighter color than the normal text color. Further this commit adds support for a more smooth transition to a bold selected font --- NYSegmentedControl/NYSegmentLabel.h | 1 + NYSegmentedControl/NYSegmentLabel.m | 176 +++++++++++++++++------- NYSegmentedControl/NYSegmentedControl.m | 11 +- 3 files changed, 131 insertions(+), 57 deletions(-) diff --git a/NYSegmentedControl/NYSegmentLabel.h b/NYSegmentedControl/NYSegmentLabel.h index 31c5a19..86a6391 100644 --- a/NYSegmentedControl/NYSegmentLabel.h +++ b/NYSegmentedControl/NYSegmentLabel.h @@ -14,5 +14,6 @@ @property (nonatomic, strong) UIColor *alternativeTextColor; @property (nonatomic, assign) CGRect maskFrame; @property (nonatomic, assign) CGFloat maskCornerRadius; +@property(nonatomic, strong) UIFont *alternativeFont; @end \ No newline at end of file diff --git a/NYSegmentedControl/NYSegmentLabel.m b/NYSegmentedControl/NYSegmentLabel.m index 2f28519..4a9a01e 100644 --- a/NYSegmentedControl/NYSegmentLabel.m +++ b/NYSegmentedControl/NYSegmentLabel.m @@ -9,8 +9,117 @@ #import "NYSegmentLabel.h" +@interface NYSegmentLabel () +@property(nonatomic, strong) NSDictionary *normalAttributes; +@property(nonatomic, strong) NSDictionary *alternativeAttributes; +@end + @implementation NYSegmentLabel +- (instancetype)init { + self = [super init]; + if (self) { + _alternativeTextColor = self.textColor; + _alternativeFont = self.font; + + [self setupAlternativeAttributes]; + } + + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _alternativeTextColor = self.textColor; + _alternativeFont = self.font; + + [self setupAlternativeAttributes]; + } + + return self; +} + +- (id)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + _alternativeTextColor = self.textColor; + _alternativeFont = self.font; + + [self setupAlternativeAttributes]; + } + + return self; +} + + +- (void)drawRect:(CGRect)rect { + CGSize size = [self.text sizeWithAttributes:self.normalAttributes]; + + // Centered rect + CGRect drawRect = CGRectMake(rect.origin.x, + rect.origin.y + (rect.size.height - size.height)/2, + rect.size.width, + (size.height)); + + // Get current context + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + + if (!CGRectIsEmpty(self.maskFrame)) { + // Frames to draw normal text within + CGRect beforeMaskFrame = CGRectMake(0, 0, CGRectGetMinX(self.maskFrame), CGRectGetHeight(self.frame)); + CGRect afterMaskFrame = CGRectMake(CGRectGetMaxX(self.maskFrame), 0, CGRectGetWidth(self.frame) - CGRectGetMaxX(self.maskFrame), CGRectGetHeight(self.frame)); + CGRect rects[2] = {beforeMaskFrame, afterMaskFrame}; + + // Clip to those frames + CGContextClipToRects(context, rects, 2); + } + + [self.text drawInRect:drawRect withAttributes:self.normalAttributes]; + + // Restore state + CGContextRestoreGState(context); + + if (!CGRectIsEmpty(self.maskFrame)) { + context = UIGraphicsGetCurrentContext(); + + // Clip to mask + CGContextClipToRect(context, self.maskFrame); + + // Draw masked text + [self.text drawInRect:drawRect withAttributes:self.alternativeAttributes]; + } +} + +#pragma mark - Private + +- (void)setupAlternativeAttributes { + NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + paragraphStyle.alignment = NSTextAlignmentCenter; + + NSDictionary *alternativeAttributes = @{ NSFontAttributeName: self.alternativeFont, + NSForegroundColorAttributeName : self.alternativeTextColor, + NSParagraphStyleAttributeName: paragraphStyle + }; + + self.alternativeAttributes = alternativeAttributes; +} + +- (void)setupNormalAttributes { + NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + paragraphStyle.alignment = NSTextAlignmentCenter; + + NSDictionary *normalAttributes = @{ NSFontAttributeName: self.font, + NSForegroundColorAttributeName : self.textColor, + NSParagraphStyleAttributeName: paragraphStyle + }; + + self.normalAttributes = normalAttributes; +} + +#pragma mark - Setters + - (void)setMaskFrame:(CGRect)maskFrame { _maskFrame = maskFrame; @@ -23,57 +132,28 @@ - (void)setMaskCornerRadius:(CGFloat)maskCornerRadius { [self setNeedsDisplay]; } -- (void)drawRect:(CGRect)rect { - CGContextRef context = UIGraphicsGetCurrentContext(); +- (void)setTextColor:(UIColor *)textColor { + [super setTextColor:textColor]; - // Draw text normally - [super drawTextInRect:rect]; - - if (self.alternativeTextColor) { - CGImageRef mask = NULL; - - // Create a mask from the text - mask = CGBitmapContextCreateImage(context); - - CGContextSaveGState(context); - CGContextTranslateCTM(context, 0, self.frame.size.height); - CGContextScaleCTM(context, 1.0, (CGFloat) -1.0); - - // Clip the current context to our mask - CGContextClipToMask(context, rect, mask); - - // Set fill color - CGContextSetFillColorWithColor(context, [self.alternativeTextColor CGColor]); - - // Path from mask - CGPathRef path; - - if (CGRectIsEmpty(self.maskFrame)) { - path = CGPathCreateMutable(); - } else { - UIBezierPath *roundRectBezierPath = [UIBezierPath bezierPathWithRoundedRect:self.maskFrame - cornerRadius:self.maskCornerRadius]; - path = CGPathCreateCopy([roundRectBezierPath CGPath]); - } - - CGContextAddPath(context, path); - - // Fill the path - CGContextFillPath(context); - CFRelease(path); - - // Clean up - CGContextRestoreGState(context); - CGImageRelease(mask); - } + [self setupNormalAttributes]; } -- (UIColor *)alternativeTextColor { - if (!_alternativeTextColor) { - _alternativeTextColor = self.textColor; - } - - return _alternativeTextColor; +- (void)setAlternativeTextColor:(UIColor *)alternativeTextColor { + _alternativeTextColor = alternativeTextColor; + + [self setupAlternativeAttributes]; +} + +- (void)setAlternativeFont:(UIFont *)alternativeFont { + _alternativeFont = alternativeFont; + + [self setupAlternativeAttributes]; +} + +- (void)setFont:(UIFont *)font { + [super setFont:font]; + + [self setupNormalAttributes]; } @end diff --git a/NYSegmentedControl/NYSegmentedControl.m b/NYSegmentedControl/NYSegmentedControl.m index 9d86812..4640866 100644 --- a/NYSegmentedControl/NYSegmentedControl.m +++ b/NYSegmentedControl/NYSegmentedControl.m @@ -174,14 +174,13 @@ - (void)layoutSubviews { if (self.stylesTitleForSelectedSegment) { if (self.selectedSegmentIndex == i) { - segment.titleLabel.font = self.selectedTitleFont; segment.titleLabel.maskFrame = segment.titleLabel.bounds; - } else { - segment.titleLabel.font = self.titleFont; } + segment.titleLabel.font = self.titleFont; segment.titleLabel.alternativeTextColor = self.selectedTitleTextColor; segment.titleLabel.textColor = self.titleTextColor; + segment.titleLabel.alternativeFont = self.selectedTitleFont; } else { segment.titleLabel.font = self.titleFont; segment.titleLabel.textColor = self.titleTextColor; @@ -262,7 +261,6 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated: duration:self.segmentIndicatorAnimationDuration options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ - previousSegment.titleLabel.font = self.titleFont; previousSegment.titleLabel.maskFrame = CGRectZero; } completion:nil]; @@ -271,11 +269,6 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated: duration:self.segmentIndicatorAnimationDuration options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ - selectedSegment.titleLabel.font = self.selectedTitleFont; - - if (self.drawsSegmentIndicatorGradientBackground) { - //selectedSegment.titleLabel.shadowColor = [UIColor darkGrayColor]; - } } completion:nil]; } From 65adf7a948363293d00184a2e327b2d3b8cb4379 Mon Sep 17 00:00:00 2001 From: Peter Gammelgaard Date: Tue, 29 Sep 2015 11:48:44 +0200 Subject: [PATCH 3/6] Revert "Changed implementation of drawRect: for the label" This reverts commit cda41c6020ea96a492780a9c809854b6e2483212. --- NYSegmentedControl/NYSegmentLabel.h | 1 - NYSegmentedControl/NYSegmentLabel.m | 176 +++++++----------------- NYSegmentedControl/NYSegmentedControl.m | 11 +- 3 files changed, 57 insertions(+), 131 deletions(-) diff --git a/NYSegmentedControl/NYSegmentLabel.h b/NYSegmentedControl/NYSegmentLabel.h index 86a6391..31c5a19 100644 --- a/NYSegmentedControl/NYSegmentLabel.h +++ b/NYSegmentedControl/NYSegmentLabel.h @@ -14,6 +14,5 @@ @property (nonatomic, strong) UIColor *alternativeTextColor; @property (nonatomic, assign) CGRect maskFrame; @property (nonatomic, assign) CGFloat maskCornerRadius; -@property(nonatomic, strong) UIFont *alternativeFont; @end \ No newline at end of file diff --git a/NYSegmentedControl/NYSegmentLabel.m b/NYSegmentedControl/NYSegmentLabel.m index 4a9a01e..2f28519 100644 --- a/NYSegmentedControl/NYSegmentLabel.m +++ b/NYSegmentedControl/NYSegmentLabel.m @@ -9,117 +9,8 @@ #import "NYSegmentLabel.h" -@interface NYSegmentLabel () -@property(nonatomic, strong) NSDictionary *normalAttributes; -@property(nonatomic, strong) NSDictionary *alternativeAttributes; -@end - @implementation NYSegmentLabel -- (instancetype)init { - self = [super init]; - if (self) { - _alternativeTextColor = self.textColor; - _alternativeFont = self.font; - - [self setupAlternativeAttributes]; - } - - return self; -} - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - _alternativeTextColor = self.textColor; - _alternativeFont = self.font; - - [self setupAlternativeAttributes]; - } - - return self; -} - -- (id)initWithCoder:(NSCoder *)coder { - self = [super initWithCoder:coder]; - if (self) { - _alternativeTextColor = self.textColor; - _alternativeFont = self.font; - - [self setupAlternativeAttributes]; - } - - return self; -} - - -- (void)drawRect:(CGRect)rect { - CGSize size = [self.text sizeWithAttributes:self.normalAttributes]; - - // Centered rect - CGRect drawRect = CGRectMake(rect.origin.x, - rect.origin.y + (rect.size.height - size.height)/2, - rect.size.width, - (size.height)); - - // Get current context - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSaveGState(context); - - if (!CGRectIsEmpty(self.maskFrame)) { - // Frames to draw normal text within - CGRect beforeMaskFrame = CGRectMake(0, 0, CGRectGetMinX(self.maskFrame), CGRectGetHeight(self.frame)); - CGRect afterMaskFrame = CGRectMake(CGRectGetMaxX(self.maskFrame), 0, CGRectGetWidth(self.frame) - CGRectGetMaxX(self.maskFrame), CGRectGetHeight(self.frame)); - CGRect rects[2] = {beforeMaskFrame, afterMaskFrame}; - - // Clip to those frames - CGContextClipToRects(context, rects, 2); - } - - [self.text drawInRect:drawRect withAttributes:self.normalAttributes]; - - // Restore state - CGContextRestoreGState(context); - - if (!CGRectIsEmpty(self.maskFrame)) { - context = UIGraphicsGetCurrentContext(); - - // Clip to mask - CGContextClipToRect(context, self.maskFrame); - - // Draw masked text - [self.text drawInRect:drawRect withAttributes:self.alternativeAttributes]; - } -} - -#pragma mark - Private - -- (void)setupAlternativeAttributes { - NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - paragraphStyle.alignment = NSTextAlignmentCenter; - - NSDictionary *alternativeAttributes = @{ NSFontAttributeName: self.alternativeFont, - NSForegroundColorAttributeName : self.alternativeTextColor, - NSParagraphStyleAttributeName: paragraphStyle - }; - - self.alternativeAttributes = alternativeAttributes; -} - -- (void)setupNormalAttributes { - NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; - paragraphStyle.alignment = NSTextAlignmentCenter; - - NSDictionary *normalAttributes = @{ NSFontAttributeName: self.font, - NSForegroundColorAttributeName : self.textColor, - NSParagraphStyleAttributeName: paragraphStyle - }; - - self.normalAttributes = normalAttributes; -} - -#pragma mark - Setters - - (void)setMaskFrame:(CGRect)maskFrame { _maskFrame = maskFrame; @@ -132,28 +23,57 @@ - (void)setMaskCornerRadius:(CGFloat)maskCornerRadius { [self setNeedsDisplay]; } -- (void)setTextColor:(UIColor *)textColor { - [super setTextColor:textColor]; - - [self setupNormalAttributes]; -} - -- (void)setAlternativeTextColor:(UIColor *)alternativeTextColor { - _alternativeTextColor = alternativeTextColor; - - [self setupAlternativeAttributes]; -} - -- (void)setAlternativeFont:(UIFont *)alternativeFont { - _alternativeFont = alternativeFont; +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); - [self setupAlternativeAttributes]; + // Draw text normally + [super drawTextInRect:rect]; + + if (self.alternativeTextColor) { + CGImageRef mask = NULL; + + // Create a mask from the text + mask = CGBitmapContextCreateImage(context); + + CGContextSaveGState(context); + CGContextTranslateCTM(context, 0, self.frame.size.height); + CGContextScaleCTM(context, 1.0, (CGFloat) -1.0); + + // Clip the current context to our mask + CGContextClipToMask(context, rect, mask); + + // Set fill color + CGContextSetFillColorWithColor(context, [self.alternativeTextColor CGColor]); + + // Path from mask + CGPathRef path; + + if (CGRectIsEmpty(self.maskFrame)) { + path = CGPathCreateMutable(); + } else { + UIBezierPath *roundRectBezierPath = [UIBezierPath bezierPathWithRoundedRect:self.maskFrame + cornerRadius:self.maskCornerRadius]; + path = CGPathCreateCopy([roundRectBezierPath CGPath]); + } + + CGContextAddPath(context, path); + + // Fill the path + CGContextFillPath(context); + CFRelease(path); + + // Clean up + CGContextRestoreGState(context); + CGImageRelease(mask); + } } -- (void)setFont:(UIFont *)font { - [super setFont:font]; - - [self setupNormalAttributes]; +- (UIColor *)alternativeTextColor { + if (!_alternativeTextColor) { + _alternativeTextColor = self.textColor; + } + + return _alternativeTextColor; } @end diff --git a/NYSegmentedControl/NYSegmentedControl.m b/NYSegmentedControl/NYSegmentedControl.m index 4640866..9d86812 100644 --- a/NYSegmentedControl/NYSegmentedControl.m +++ b/NYSegmentedControl/NYSegmentedControl.m @@ -174,13 +174,14 @@ - (void)layoutSubviews { if (self.stylesTitleForSelectedSegment) { if (self.selectedSegmentIndex == i) { + segment.titleLabel.font = self.selectedTitleFont; segment.titleLabel.maskFrame = segment.titleLabel.bounds; + } else { + segment.titleLabel.font = self.titleFont; } - segment.titleLabel.font = self.titleFont; segment.titleLabel.alternativeTextColor = self.selectedTitleTextColor; segment.titleLabel.textColor = self.titleTextColor; - segment.titleLabel.alternativeFont = self.selectedTitleFont; } else { segment.titleLabel.font = self.titleFont; segment.titleLabel.textColor = self.titleTextColor; @@ -261,6 +262,7 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated: duration:self.segmentIndicatorAnimationDuration options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ + previousSegment.titleLabel.font = self.titleFont; previousSegment.titleLabel.maskFrame = CGRectZero; } completion:nil]; @@ -269,6 +271,11 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated: duration:self.segmentIndicatorAnimationDuration options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ + selectedSegment.titleLabel.font = self.selectedTitleFont; + + if (self.drawsSegmentIndicatorGradientBackground) { + //selectedSegment.titleLabel.shadowColor = [UIColor darkGrayColor]; + } } completion:nil]; } From 3fcee3f3fe7e9154b8754132bdd53a6ed02cfb3f Mon Sep 17 00:00:00 2001 From: Peter Gammelgaard Date: Tue, 29 Sep 2015 11:50:16 +0200 Subject: [PATCH 4/6] Revert "Merge remote-tracking branch 'upstream/master'" This reverts commit 49da75e76b001550360cb3e17b8ace2fceb6989b, reversing changes made to 66125d92ee1785abb2c50d26aef872001c4e7456. --- NYSegmentedControl.podspec | 2 +- NYSegmentedControl/NYSegmentLabel.m | 23 ++++++++-------- NYSegmentedControl/NYSegmentedControl.h | 26 +++++++------------ NYSegmentedControl/NYSegmentedControl.m | 5 ---- .../AppIcon.appiconset/Contents.json | 10 ------- 5 files changed, 21 insertions(+), 45 deletions(-) diff --git a/NYSegmentedControl.podspec b/NYSegmentedControl.podspec index e082a49..c63a2b7 100644 --- a/NYSegmentedControl.podspec +++ b/NYSegmentedControl.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "NYSegmentedControl" - s.version = "1.0.7" + s.version = "1.0.5" s.summary = "Animated, customizable replacement for UISegmentedControl" s.description = "NYSegmentedControl is a customizable, animated replacement for UISegmentedControl inspired by controls found in Instagram, Foursquare, and other apps." s.homepage = "https://github.com/nealyoung/NYSegmentedControl" diff --git a/NYSegmentedControl/NYSegmentLabel.m b/NYSegmentedControl/NYSegmentLabel.m index 2f28519..53a5b7c 100644 --- a/NYSegmentedControl/NYSegmentLabel.m +++ b/NYSegmentedControl/NYSegmentLabel.m @@ -46,21 +46,11 @@ - (void)drawRect:(CGRect)rect { CGContextSetFillColorWithColor(context, [self.alternativeTextColor CGColor]); // Path from mask - CGPathRef path; - - if (CGRectIsEmpty(self.maskFrame)) { - path = CGPathCreateMutable(); - } else { - UIBezierPath *roundRectBezierPath = [UIBezierPath bezierPathWithRoundedRect:self.maskFrame - cornerRadius:self.maskCornerRadius]; - path = CGPathCreateCopy([roundRectBezierPath CGPath]); - } - + CGPathRef path = [self pathForRoundedRect:self.maskFrame radius:self.maskCornerRadius]; CGContextAddPath(context, path); - + // Fill the path CGContextFillPath(context); - CFRelease(path); // Clean up CGContextRestoreGState(context); @@ -68,6 +58,15 @@ - (void)drawRect:(CGRect)rect { } } +- (CGPathRef)pathForRoundedRect:(CGRect)rect radius:(CGFloat)radius { + if (CGRectIsEmpty(rect)) { + return CGPathCreateMutable(); + } + + UIBezierPath* path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius]; + return [path CGPath]; +} + - (UIColor *)alternativeTextColor { if (!_alternativeTextColor) { _alternativeTextColor = self.textColor; diff --git a/NYSegmentedControl/NYSegmentedControl.h b/NYSegmentedControl/NYSegmentedControl.h index b3e3ac9..64759d7 100644 --- a/NYSegmentedControl/NYSegmentedControl.h +++ b/NYSegmentedControl/NYSegmentedControl.h @@ -23,7 +23,12 @@ /** Data source of segment items */ -@property (weak, nonatomic) IBOutlet id dataSource; +@property (weak) IBOutlet id dataSource; + +/** + Reload items data if dataSource is defined + */ +- (void) reloadData; /** If YES, selectedTitleFont and SelectedTitleTextColor are used for the selected segment's title label. The default value is YES. @@ -147,28 +152,22 @@ #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0 /** - If set to YES, UIView spring animations will be used to animate the position of the segment indicator + If `YES`, than use UIView spring animations to animate the motion of the segment indicator */ @property (nonatomic) BOOL usesSpringAnimations UI_APPEARANCE_SELECTOR; /** The animation duration used if spring animations are enabled - - @see usesSpringAnimations */ @property (nonatomic) CGFloat springAnimationDuration UI_APPEARANCE_SELECTOR; /** - The damping ratio for the spring animation used if spring animations are enabled - - @see usesSpringAnimations + The damping ratio for the spring animation */ @property (nonatomic) CGFloat springAnimationDampingRatio UI_APPEARANCE_SELECTOR; /** - The initial spring velocity used if spring animations are enabled - - @see usesSpringAnimations + The initial spring velocity */ @property (nonatomic) CGFloat springAnimationVelocity UI_APPEARANCE_SELECTOR; @@ -228,11 +227,4 @@ */ - (void)setSelectedSegmentIndex:(NSUInteger)selectedSegmentIndex animated:(BOOL)animated; -/** - Reloads the control's items from its data source, if defined - - @see dataSource - */ -- (void)reloadData; - @end diff --git a/NYSegmentedControl/NYSegmentedControl.m b/NYSegmentedControl/NYSegmentedControl.m index 9d86812..2d08c9e 100644 --- a/NYSegmentedControl/NYSegmentedControl.m +++ b/NYSegmentedControl/NYSegmentedControl.m @@ -438,11 +438,6 @@ - (BOOL)drawsSegmentIndicatorGradientBackground { return self.selectedSegmentIndicator.drawsGradientBackground; } -- (void)setBounds:(CGRect)bounds { - [super setBounds:bounds]; - self.selectedSegmentIndicator.cornerRadius = self.cornerRadius * ((self.frame.size.height - self.segmentIndicatorInset * 2) / self.frame.size.height); -} - - (void)setFrame:(CGRect)frame { [super setFrame:frame]; self.selectedSegmentIndicator.cornerRadius = self.cornerRadius * ((self.frame.size.height - self.segmentIndicatorInset * 2) / self.frame.size.height); diff --git a/NYSegmentedControlDemo/NYSegmentedControlDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/NYSegmentedControlDemo/NYSegmentedControlDemo/Images.xcassets/AppIcon.appiconset/Contents.json index 118c98f..33ec0bc 100644 --- a/NYSegmentedControlDemo/NYSegmentedControlDemo/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/NYSegmentedControlDemo/NYSegmentedControlDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -5,21 +5,11 @@ "size" : "29x29", "scale" : "2x" }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, { "idiom" : "iphone", "size" : "60x60", From 10ac8e37ef7a4701f22b3ace4fba69981de381ee Mon Sep 17 00:00:00 2001 From: Peter Gammelgaard Date: Wed, 30 Sep 2015 09:10:09 +0200 Subject: [PATCH 5/6] Revert "Revert "Merge remote-tracking branch 'upstream/master'"" This reverts commit 3fcee3f3fe7e9154b8754132bdd53a6ed02cfb3f. --- NYSegmentedControl.podspec | 2 +- NYSegmentedControl/NYSegmentLabel.m | 23 ++++++++-------- NYSegmentedControl/NYSegmentedControl.h | 26 ++++++++++++------- NYSegmentedControl/NYSegmentedControl.m | 5 ++++ .../AppIcon.appiconset/Contents.json | 10 +++++++ 5 files changed, 45 insertions(+), 21 deletions(-) diff --git a/NYSegmentedControl.podspec b/NYSegmentedControl.podspec index c63a2b7..e082a49 100644 --- a/NYSegmentedControl.podspec +++ b/NYSegmentedControl.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "NYSegmentedControl" - s.version = "1.0.5" + s.version = "1.0.7" s.summary = "Animated, customizable replacement for UISegmentedControl" s.description = "NYSegmentedControl is a customizable, animated replacement for UISegmentedControl inspired by controls found in Instagram, Foursquare, and other apps." s.homepage = "https://github.com/nealyoung/NYSegmentedControl" diff --git a/NYSegmentedControl/NYSegmentLabel.m b/NYSegmentedControl/NYSegmentLabel.m index 53a5b7c..2f28519 100644 --- a/NYSegmentedControl/NYSegmentLabel.m +++ b/NYSegmentedControl/NYSegmentLabel.m @@ -46,11 +46,21 @@ - (void)drawRect:(CGRect)rect { CGContextSetFillColorWithColor(context, [self.alternativeTextColor CGColor]); // Path from mask - CGPathRef path = [self pathForRoundedRect:self.maskFrame radius:self.maskCornerRadius]; + CGPathRef path; + + if (CGRectIsEmpty(self.maskFrame)) { + path = CGPathCreateMutable(); + } else { + UIBezierPath *roundRectBezierPath = [UIBezierPath bezierPathWithRoundedRect:self.maskFrame + cornerRadius:self.maskCornerRadius]; + path = CGPathCreateCopy([roundRectBezierPath CGPath]); + } + CGContextAddPath(context, path); - + // Fill the path CGContextFillPath(context); + CFRelease(path); // Clean up CGContextRestoreGState(context); @@ -58,15 +68,6 @@ - (void)drawRect:(CGRect)rect { } } -- (CGPathRef)pathForRoundedRect:(CGRect)rect radius:(CGFloat)radius { - if (CGRectIsEmpty(rect)) { - return CGPathCreateMutable(); - } - - UIBezierPath* path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius]; - return [path CGPath]; -} - - (UIColor *)alternativeTextColor { if (!_alternativeTextColor) { _alternativeTextColor = self.textColor; diff --git a/NYSegmentedControl/NYSegmentedControl.h b/NYSegmentedControl/NYSegmentedControl.h index 64759d7..b3e3ac9 100644 --- a/NYSegmentedControl/NYSegmentedControl.h +++ b/NYSegmentedControl/NYSegmentedControl.h @@ -23,12 +23,7 @@ /** Data source of segment items */ -@property (weak) IBOutlet id dataSource; - -/** - Reload items data if dataSource is defined - */ -- (void) reloadData; +@property (weak, nonatomic) IBOutlet id dataSource; /** If YES, selectedTitleFont and SelectedTitleTextColor are used for the selected segment's title label. The default value is YES. @@ -152,22 +147,28 @@ #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0 /** - If `YES`, than use UIView spring animations to animate the motion of the segment indicator + If set to YES, UIView spring animations will be used to animate the position of the segment indicator */ @property (nonatomic) BOOL usesSpringAnimations UI_APPEARANCE_SELECTOR; /** The animation duration used if spring animations are enabled + + @see usesSpringAnimations */ @property (nonatomic) CGFloat springAnimationDuration UI_APPEARANCE_SELECTOR; /** - The damping ratio for the spring animation + The damping ratio for the spring animation used if spring animations are enabled + + @see usesSpringAnimations */ @property (nonatomic) CGFloat springAnimationDampingRatio UI_APPEARANCE_SELECTOR; /** - The initial spring velocity + The initial spring velocity used if spring animations are enabled + + @see usesSpringAnimations */ @property (nonatomic) CGFloat springAnimationVelocity UI_APPEARANCE_SELECTOR; @@ -227,4 +228,11 @@ */ - (void)setSelectedSegmentIndex:(NSUInteger)selectedSegmentIndex animated:(BOOL)animated; +/** + Reloads the control's items from its data source, if defined + + @see dataSource + */ +- (void)reloadData; + @end diff --git a/NYSegmentedControl/NYSegmentedControl.m b/NYSegmentedControl/NYSegmentedControl.m index 2d08c9e..9d86812 100644 --- a/NYSegmentedControl/NYSegmentedControl.m +++ b/NYSegmentedControl/NYSegmentedControl.m @@ -438,6 +438,11 @@ - (BOOL)drawsSegmentIndicatorGradientBackground { return self.selectedSegmentIndicator.drawsGradientBackground; } +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + self.selectedSegmentIndicator.cornerRadius = self.cornerRadius * ((self.frame.size.height - self.segmentIndicatorInset * 2) / self.frame.size.height); +} + - (void)setFrame:(CGRect)frame { [super setFrame:frame]; self.selectedSegmentIndicator.cornerRadius = self.cornerRadius * ((self.frame.size.height - self.segmentIndicatorInset * 2) / self.frame.size.height); diff --git a/NYSegmentedControlDemo/NYSegmentedControlDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/NYSegmentedControlDemo/NYSegmentedControlDemo/Images.xcassets/AppIcon.appiconset/Contents.json index 33ec0bc..118c98f 100644 --- a/NYSegmentedControlDemo/NYSegmentedControlDemo/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/NYSegmentedControlDemo/NYSegmentedControlDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -5,11 +5,21 @@ "size" : "29x29", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "60x60", From 3df1eb25aa0d00a2f0d97dd51202958195fe3012 Mon Sep 17 00:00:00 2001 From: Peter Gammelgaard Date: Wed, 30 Sep 2015 09:17:38 +0200 Subject: [PATCH 6/6] Changed implementation of drawRect: for the label This is done to avoid a visual glitch when the selected title color is in a lighter color than the normal text color. Further this commit adds support for a more smooth transition to a bold selected font --- NYSegmentedControl/NYSegmentLabel.h | 1 + NYSegmentedControl/NYSegmentLabel.m | 173 +++++++++++++++++------- NYSegmentedControl/NYSegmentedControl.m | 18 +-- 3 files changed, 128 insertions(+), 64 deletions(-) diff --git a/NYSegmentedControl/NYSegmentLabel.h b/NYSegmentedControl/NYSegmentLabel.h index 31c5a19..86a6391 100644 --- a/NYSegmentedControl/NYSegmentLabel.h +++ b/NYSegmentedControl/NYSegmentLabel.h @@ -14,5 +14,6 @@ @property (nonatomic, strong) UIColor *alternativeTextColor; @property (nonatomic, assign) CGRect maskFrame; @property (nonatomic, assign) CGFloat maskCornerRadius; +@property(nonatomic, strong) UIFont *alternativeFont; @end \ No newline at end of file diff --git a/NYSegmentedControl/NYSegmentLabel.m b/NYSegmentedControl/NYSegmentLabel.m index 2f28519..78e18ad 100644 --- a/NYSegmentedControl/NYSegmentLabel.m +++ b/NYSegmentedControl/NYSegmentLabel.m @@ -9,8 +9,114 @@ #import "NYSegmentLabel.h" +@interface NYSegmentLabel () +@property(nonatomic, strong) NSDictionary *normalAttributes; +@property(nonatomic, strong) NSDictionary *alternativeAttributes; +@end + @implementation NYSegmentLabel +- (instancetype)init { + self = [super init]; + if (self) { + [self commonInit]; + } + + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self commonInit]; + } + + return self; +} + +- (id)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self commonInit]; + } + + return self; +} + +- (void)commonInit { + _alternativeTextColor = self.textColor; + _alternativeFont = self.font; + + [self setupAlternativeAttributes]; +} + +- (void)drawRect:(CGRect)rect { + CGSize size = [self.text sizeWithAttributes:self.normalAttributes]; + + // Centered rect + CGRect drawRect = CGRectMake(rect.origin.x, + rect.origin.y + (rect.size.height - size.height)/2, + rect.size.width, + (size.height)); + + // Get current context + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + + if (!CGRectIsEmpty(self.maskFrame)) { + // Frames to draw normal text within + CGRect beforeMaskFrame = CGRectMake(0, 0, CGRectGetMinX(self.maskFrame), CGRectGetHeight(self.frame)); + CGRect afterMaskFrame = CGRectMake(CGRectGetMaxX(self.maskFrame), 0, CGRectGetWidth(self.frame) - CGRectGetMaxX(self.maskFrame), CGRectGetHeight(self.frame)); + CGRect rects[2] = {beforeMaskFrame, afterMaskFrame}; + + // Clip to those frames + CGContextClipToRects(context, rects, 2); + } + + [self.text drawInRect:drawRect withAttributes:self.normalAttributes]; + + // Restore state + CGContextRestoreGState(context); + + if (!CGRectIsEmpty(self.maskFrame)) { + context = UIGraphicsGetCurrentContext(); + + // Clip to mask + CGContextClipToRect(context, self.maskFrame); + + // Draw masked text + [self.text drawInRect:drawRect withAttributes:self.alternativeAttributes]; + } +} + +#pragma mark - Private + +- (void)setupAlternativeAttributes { + NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + paragraphStyle.alignment = NSTextAlignmentCenter; + + NSDictionary *alternativeAttributes = @{ NSFontAttributeName: self.alternativeFont, + NSForegroundColorAttributeName : self.alternativeTextColor, + NSParagraphStyleAttributeName: paragraphStyle + }; + + self.alternativeAttributes = alternativeAttributes; +} + +- (void)setupNormalAttributes { + NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + paragraphStyle.alignment = NSTextAlignmentCenter; + + NSDictionary *normalAttributes = @{ NSFontAttributeName: self.font, + NSForegroundColorAttributeName : self.textColor, + NSParagraphStyleAttributeName: paragraphStyle + }; + + self.normalAttributes = normalAttributes; +} + +#pragma mark - Setters + - (void)setMaskFrame:(CGRect)maskFrame { _maskFrame = maskFrame; @@ -23,57 +129,28 @@ - (void)setMaskCornerRadius:(CGFloat)maskCornerRadius { [self setNeedsDisplay]; } -- (void)drawRect:(CGRect)rect { - CGContextRef context = UIGraphicsGetCurrentContext(); +- (void)setTextColor:(UIColor *)textColor { + [super setTextColor:textColor]; - // Draw text normally - [super drawTextInRect:rect]; - - if (self.alternativeTextColor) { - CGImageRef mask = NULL; - - // Create a mask from the text - mask = CGBitmapContextCreateImage(context); - - CGContextSaveGState(context); - CGContextTranslateCTM(context, 0, self.frame.size.height); - CGContextScaleCTM(context, 1.0, (CGFloat) -1.0); - - // Clip the current context to our mask - CGContextClipToMask(context, rect, mask); - - // Set fill color - CGContextSetFillColorWithColor(context, [self.alternativeTextColor CGColor]); - - // Path from mask - CGPathRef path; - - if (CGRectIsEmpty(self.maskFrame)) { - path = CGPathCreateMutable(); - } else { - UIBezierPath *roundRectBezierPath = [UIBezierPath bezierPathWithRoundedRect:self.maskFrame - cornerRadius:self.maskCornerRadius]; - path = CGPathCreateCopy([roundRectBezierPath CGPath]); - } - - CGContextAddPath(context, path); - - // Fill the path - CGContextFillPath(context); - CFRelease(path); - - // Clean up - CGContextRestoreGState(context); - CGImageRelease(mask); - } + [self setupNormalAttributes]; } -- (UIColor *)alternativeTextColor { - if (!_alternativeTextColor) { - _alternativeTextColor = self.textColor; - } - - return _alternativeTextColor; +- (void)setAlternativeTextColor:(UIColor *)alternativeTextColor { + _alternativeTextColor = alternativeTextColor; + + [self setupAlternativeAttributes]; +} + +- (void)setAlternativeFont:(UIFont *)alternativeFont { + _alternativeFont = alternativeFont; + + [self setupAlternativeAttributes]; +} + +- (void)setFont:(UIFont *)font { + [super setFont:font]; + + [self setupNormalAttributes]; } @end diff --git a/NYSegmentedControl/NYSegmentedControl.m b/NYSegmentedControl/NYSegmentedControl.m index 9d86812..a1d6f5c 100644 --- a/NYSegmentedControl/NYSegmentedControl.m +++ b/NYSegmentedControl/NYSegmentedControl.m @@ -174,14 +174,13 @@ - (void)layoutSubviews { if (self.stylesTitleForSelectedSegment) { if (self.selectedSegmentIndex == i) { - segment.titleLabel.font = self.selectedTitleFont; segment.titleLabel.maskFrame = segment.titleLabel.bounds; - } else { - segment.titleLabel.font = self.titleFont; } + segment.titleLabel.font = self.titleFont; segment.titleLabel.alternativeTextColor = self.selectedTitleTextColor; segment.titleLabel.textColor = self.titleTextColor; + segment.titleLabel.alternativeFont = self.selectedTitleFont; } else { segment.titleLabel.font = self.titleFont; segment.titleLabel.textColor = self.titleTextColor; @@ -262,7 +261,6 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated: duration:self.segmentIndicatorAnimationDuration options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ - previousSegment.titleLabel.font = self.titleFont; previousSegment.titleLabel.maskFrame = CGRectZero; } completion:nil]; @@ -271,11 +269,6 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated: duration:self.segmentIndicatorAnimationDuration options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ - selectedSegment.titleLabel.font = self.selectedTitleFont; - - if (self.drawsSegmentIndicatorGradientBackground) { - //selectedSegment.titleLabel.shadowColor = [UIColor darkGrayColor]; - } } completion:nil]; } @@ -310,7 +303,6 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated: self.selectedSegmentIndicator.frame = [self indicatorFrameForSegment:selectedSegment]; if (self.stylesTitleForSelectedSegment) { - selectedSegment.titleLabel.font = self.selectedTitleFont; selectedSegment.titleLabel.maskFrame = selectedSegment.titleLabel.bounds; } } @@ -324,12 +316,6 @@ - (void)panGestureRecognized:(UIPanGestureRecognizer *)panGestureRecognizer { if (self.stylesTitleForSelectedSegment) { // Style the segment the center of the indicator is covering [self.segments enumerateObjectsUsingBlock:^(NYSegment *segment, NSUInteger index, BOOL *stop) { - if (CGRectContainsPoint(segment.frame, self.selectedSegmentIndicator.center)) { - segment.titleLabel.font = self.selectedTitleFont; - } else { - segment.titleLabel.font = self.titleFont; - } - CGRect segmentFrame = segment.frame; CGRect intersection = CGRectIntersection(segmentFrame, self.selectedSegmentIndicator.frame); CGAffineTransform transform = CGAffineTransformMakeTranslation(-CGRectGetMinX(segmentFrame), -CGRectGetMinY(segmentFrame));