更新:さらに微調整を行いましたが、まだ完璧ではありませんが、これは適切な近似値を提供しているようで、ピクセルを与えるか取るかです。
コントロールが小さい限り、上記はうまく機能しますが、いくつかのエラーがあります。おそらく、数ピクセル分のサイズをどこかに取り込んでいないためです。
テスト アプリで行ったことは次のとおりです(注:プロジェクトは更新され、より多くのテスト コントロールが追加されています)。
最初に、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 の両方で機能しますが、ハーフ ピクセル エラーがときどき発生するようです。
結果を以下に示します。