Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NYSegmentedControl/NYSegmentLabel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
173 changes: 125 additions & 48 deletions NYSegmentedControl/NYSegmentLabel.m
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
20 changes: 2 additions & 18 deletions NYSegmentedControl/NYSegmentedControl.m
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -262,8 +261,6 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated:
duration:self.segmentIndicatorAnimationDuration
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
previousSegment.titleLabel.font = self.titleFont;
previousSegment.titleLabel.textColor = self.titleTextColor;
previousSegment.titleLabel.maskFrame = CGRectZero;
}
completion:nil];
Expand All @@ -272,12 +269,6 @@ - (void)moveSelectedSegmentIndicatorToSegmentAtIndex:(NSUInteger)index animated:
duration:self.segmentIndicatorAnimationDuration
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
selectedSegment.titleLabel.font = self.selectedTitleFont;
selectedSegment.titleLabel.textColor = self.selectedTitleTextColor;

if (self.drawsSegmentIndicatorGradientBackground) {
//selectedSegment.titleLabel.shadowColor = [UIColor darkGrayColor];
}
}
completion:nil];
}
Expand Down Expand Up @@ -312,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;
}
}
Expand All @@ -326,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));
Expand Down