更新:我做了更多的调整,但我仍然没有完美,但这似乎给出了一个很好的近似值,给或取一个像素。
只要控件很小,那么上面的效果很好,但是有一些错误。可能是因为我没有在某个地方接收几个像素大小的值。
这是我在测试应用程序中所做的(注意:该项目已更新以具有更多测试控件)。
首先,我在 UISegmentedControl 类上声明了一个类扩展:
@interface UISegmentedControl (Overload)
- (NSArray*)mapUISegmentedControl;
@end
然后,我实现它,如下所示:
@implementation UISegmentedControl (Overload)
- (NSArray*)mapUISegmentedControl
{
NSMutableArray *segmentFrames = [NSMutableArray arrayWithCapacity:[self numberOfSegments]];
NSInteger numberOfAutosizedSegments = 0;
double ios7Coefficient = [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 ? 1 : 0;
double autosizedWidth = CGRectGetWidth ( [self bounds] ) - 1;
for ( NSInteger i = 0; i < [self numberOfSegments]; i++ )
{
double width = [self widthForSegmentAtIndex:i];
if ( width == 0.0f )
{
autosizedWidth -= 1;
// If this is an auto-sized, we blank out the holding space for it.
numberOfAutosizedSegments++; // Add this to our count of auto-sized segments.
[segmentFrames addObject:[NSNull null]];
}
else
{
// If the size has been explicitly set, we use that, and create a simple rect.
autosizedWidth -= (width + ios7Coefficient);
CGRect frame = CGRectMake ( 0, 0, width, CGRectGetHeight ( [self bounds] ) );
[segmentFrames addObject:[NSValue valueWithCGRect:frame]];
}
}
// We divvy up the leftover space for the autoscales.
double autoWidth = (autosizedWidth + ios7Coefficient) / (double)numberOfAutosizedSegments;
double x = 0;
for ( NSInteger i = 0; i < [segmentFrames count]; i++ )
{
CGRect frame = CGRectZero;
double width = 0;
// If this is auto-sized (flagged by a null object), then make an autosized rect.
if ( segmentFrames[i] == [NSNull null] )
{
width = ceil ( autoWidth - ios7Coefficient );
}
else // Otherwise, use the rect they supplied.
{
width = CGRectGetWidth ( [(NSValue*)[segmentFrames objectAtIndex:i] CGRectValue] );
}
width += 1;
frame = CGRectMake ( x, 0, width, CGRectGetHeight( [self bounds] ) );
[segmentFrames replaceObjectAtIndex:i
withObject:[NSValue valueWithCGRect:frame]
];
// The x origin keeps up with the control.
x += width;
}
return [NSArray arrayWithArray:segmentFrames];
}
@end
接下来,我在布局响应中调用它,如下所示:
@implementation DemoViewController
- (void)drawOverlays
{
NSArray *segmentMap = [[self segmentedControl] mapUISegmentedControl];
if ( ![self colorBand] )
{
_colorBand = [[NSMutableArray alloc] init];
}
else
{
for ( UIView *view in [self colorBand] )
{
[view removeFromSuperview];
}
[[self colorBand] removeAllObjects];
}
for ( NSInteger i = 0; i < [segmentMap count]; i++ )
{
CGRect frame = [(NSValue*)[segmentMap objectAtIndex:i] CGRectValue];
frame.size.height /= 2.0;
frame.origin.y = [[self segmentedControl] frame].origin.y + [[self segmentedControl] frame].size.height;
UIView *view = [[UIView alloc] initWithFrame:frame];
view.backgroundColor = [UIColor colorWithHue:i/(float)[segmentMap count] saturation:1 brightness:1 alpha:0.5];
[[self view] addSubview:view];
[[self colorBand] addObject:view];
}
}
- (void)viewDidLayoutSubviews
{
[self drawOverlays];
}
@end
这在 iOS 6 和 7 中都有效,但有时似乎偶尔会出现半像素错误。
结果如下所示:
![iOS6](https://i.stack.imgur.com/H74On.png)
![IOS 7](https://i.stack.imgur.com/EiZLl.png)