Reputation: 336
I'm trying to extend the functionality of the UISegmentedControl and I'm running into some issues with working with individual segments. The problem seems to be relatively generic, so I'm borrowing some code from an example on-line: http://www.framewreck.net/2010/07/custom-tintcolor-for-each-segment-of.html
For easy reference:
UISegmentedControlExtension.h
@interface UISegmentedControl(CustomTintExtension)
-(void)setTag:(NSInteger)tag forSegmentAtIndex:(NSUInteger)segment;
-(void)setTintColor:(UIColor*)color forTag:(NSInteger)aTag;
-(void)setTextColor:(UIColor*)color forTag:(NSInteger)aTag;
-(void)setShadowColor:(UIColor*)color forTag:(NSInteger)aTag;
@end
UISegmentedControlExtension.m
#import "UISegmentedControlExtension.h"
@implementation UISegmentedControl(CustomTintExtension)
-(void)setTag:(NSInteger)tag forSegmentAtIndex:(NSUInteger)segment {
[[[self subviews] objectAtIndex:segment] setTag:tag];
}
-(void)setTintColor:(UIColor*)color forTag:(NSInteger)aTag {
// must operate by tags. Subview index is unreliable
UIView *segment = [self viewWithTag:aTag];
SEL tint = @selector(setTintColor:);
// UISegment is an undocumented class, so tread carefully
// if the segment exists and if it responds to the setTintColor message
if (segment && ([segment respondsToSelector:tint])) {
[segment performSelector:tint withObject:color];
}
}
-(void)setTextColor:(UIColor*)color forTag:(NSInteger)aTag {
UIView *segment = [self viewWithTag:aTag];
for (UIView *view in segment.subviews) {
SEL text = @selector(setTextColor:);
// if the sub view exists and if it responds to the setTextColor message
if (view && ([view respondsToSelector:text])) {
[view performSelector:text withObject:color];
}
}
}
-(void)setShadowColor:(UIColor*)color forTag:(NSInteger)aTag {
// you probably know the drill by now
// you could also combine setShadowColor and setTextColor
UIView *segment = [self viewWithTag:aTag];
for (UIView *view in segment.subviews) {
SEL shadowColor = @selector(setShadowColor:);
if (view && ([view respondsToSelector:shadowColor])) {
[view performSelector:shadowColor withObject:color];
}
}
}
@end
The above example claims that "at some point later, the segment indexes change" -- I don't believe this is the case, but there is definitely something strange going on with the indexes from something like:
[_segmentedControl titleForSegmentAtIndex:i]
and then using the example's code:
[_segmentedControl setTintColor:[UIColor blueColor] forTag:Blue];
If I go through and map the indexes of each segment using the title of the segment:
typedef NS_ENUM(int, colorvalues) {
Blue, Brown, Green, Red, White, Yellow
};
if ([@"Blue" isEqual: title]) {
NSLog(@"Setting Blue(%d) tag on segment: %d", Blue, i);
[_segmentedControl setTag:Blue forSegmentAtIndex:i];
} else if ([@"Brown" isEqual: title]) {
NSLog(@"Setting Brown tag on segment: %d", i);
[_segmentedControl setTag:Brown forSegmentAtIndex:i];
} else if ([@"Green" isEqual: title]) {
NSLog(@"Setting Green tag on segment: %d", i);
[_segmentedControl setTag:Green forSegmentAtIndex:i];
} else if ([@"Red" isEqual: title]) {
NSLog(@"Setting Red tag on segment: %d", i);
[_segmentedControl setTag:Red forSegmentAtIndex:i];
} else if ([@"White" isEqual: title]) {
NSLog(@"Setting White tag on segment: %d", i);
[_segmentedControl setTag:White forSegmentAtIndex:i];
} else if ([@"Yellow" isEqual: title]) {
NSLog(@"Setting Yellow tag on segment: %d", i);
[_segmentedControl setTag:Yellow forSegmentAtIndex:i];
}
and then set the Tint using the example code above:
[_segmentedControl setTintColor:[UIColor blueColor] forTag:Blue];
[_segmentedControl setTintColor:[UIColor brownColor] forTag:Brown];
[_segmentedControl setTintColor:[UIColor greenColor] forTag:Green];
[_segmentedControl setTintColor:[UIColor redColor] forTag:Red];
[_segmentedControl setTintColor:[UIColor whiteColor] forTag:White];
[_segmentedControl setTintColor:[UIColor yellowColor] forTag:Yellow];
I end up with:
If I create the UISegmentedControl programmatically I can influence the offsetting of the indexing by setting the selected segment before adding it to the subview. With the selected segment set to 0 things line up correctly. However through the interface builder things are consistently broken, even when choosing a different selected segment via the GUI. I'm assuming because the control is being added to the subview before the segment is selected.
Any ideas what's causing this strange behavior?
Upvotes: 1
Views: 751
Reputation: 245
[[[self subviews] objectAtIndex:segment] setTag:tag];
This line has problem. Set the segments in reverse order. Eg.
#define kTagSecond 222
#define kTagFirst 111
[self.segment setTag:kTagFirst forSegmentAtIndex:1];
[self.segment setTag:kTagSecond forSegmentAtIndex:0];
Where kTagFirst is the first segment and kTagSecond is the second segment
Upvotes: 1