Как рассчитать правильную ширину для сегментов UISegmentedControl?
Я пытаюсь использовать UISegmentedControl, но не могу вычислить ширину сегментов. Элемент управления делает сегменты одинаковой ширины, которые не работают для некоторых заголовков, например:
http://morrisphotoart.com/tmp/Screenshot2011-07-13_21.17.33.png
Я могу написать код для вычисления ширины сегмента, если бы я знал, какой шрифт и вызывается метод setWidth: forSegmentAtIndex:, но как я могу получить шрифт? Или есть другой способ?
Заголовки в левом и среднем сегментах не фиксируются, поэтому я не могу кодировать ширину.
Ответы
Ответ 1
Если вы можете поддерживать iOS 5 и позже, вы можете использовать свойство apportionsSegmentWidthsByContent
и установить его на YES
.
Из iOS 5 docs:
apportionsSegmentWidthsByContent
Указывает, будет ли элемент управления пытается настроить ширину сегмента в зависимости от их ширины содержимого.
@property (неатомные) BOOL apportionsSegmentWidthsByContent
Обсуждение
Если значение этого свойства равно YES, для сегментов, значение ширины которых 0, управление пытается отрегулировать ширину сегмента на основе их ширины содержимого.
Ответ 2
EDIT: проще использовать функцию iOS 5 apportionsSegmentWidthsByContent
, как указано в @Camsoft здесь, здесь
Ну, я закончил тем, что UIFont выкарабкался через subviews (который может сломаться в будущем iOS). Будучи модульным/повторным использованием aficianado, я написал эту процедуру, чтобы сделать это, а затем распределить пространство, чтобы сегменты в элементе управления были равномерно распределены между заголовками.
-(void)resizeSegmentsToFitTitles:(UISegmentedControl*)segCtrl {
CGFloat totalWidths = 0; // total of all label text widths
NSUInteger nSegments = segCtrl.subviews.count;
UIView* aSegment = [segCtrl.subviews objectAtIndex:0];
UIFont* theFont = nil;
for (UILabel* aLabel in aSegment.subviews) {
if ([aLabel isKindOfClass:[UILabel class]]) {
theFont = aLabel.font;
break;
}
}
// calculate width that all the title text takes up
for (NSUInteger i=0; i < nSegments; i++) {
CGFloat textWidth = [[segCtrl titleForSegmentAtIndex:i] sizeWithFont:theFont].width;
totalWidths += textWidth;
}
// width not used up by text, its the space between labels
CGFloat spaceWidth = segCtrl.bounds.size.width - totalWidths;
// now resize the segments to accomodate text size plus
// give them each an equal part of the leftover space
for (NSUInteger i=0; i < nSegments; i++) {
// size for label width plus an equal share of the space
CGFloat textWidth = [[segCtrl titleForSegmentAtIndex:i] sizeWithFont:theFont].width;
// roundf?? the control leaves 1 pixel gap between segments if width
// is not an integer value, the roundf fixes this
CGFloat segWidth = roundf(textWidth + (spaceWidth / nSegments));
[segCtrl setWidth:segWidth forSegmentAtIndex:i];
}
}
Ответ 3
NSArray *itemArray = [NSArray arrayWithObjects: @"Title1", @"Title2", @"Titl3", @"Title4",nil];
segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(0, 0, 310, 35);
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.selectedSegmentIndex = 0;
[segmentedControl addTarget:self action:@selector(pickOne:) forControlEvents:UIControlEventValueChanged];
segmentedControl.tintColor=[UIColor grayColor];
for (id segment in [segmentedControl subviews])
{
for (id label in [segment subviews])
{
if ([label isKindOfClass:[UILabel class]])
{
[label setTextAlignment:UITextAlignmentCenter];
[label setFont:[UIFont boldSystemFontOfSize:12]];
}
}
}
Ответ 4
iOS 7.1.1 дружественный. Мы вычислили только размер нового кадра UISegmentedControl, а остальные (пропорции сегментов) будут обрабатываться iOS (на основе apportionsSegmentWidthsByContent).
Имейте в виду, что это не работает, если Автомакет включен.
void styleSegment_fitTitles(UISegmentedControl *segCtrl) {
// Fit segments' titles
[segCtrl sizeToFit];
CGFloat em = font.pointSize;
CGRect segCtrlRect = segCtrl.bounds;
CGFloat segCtrlWidth = segCtrlRect.size.width + segCtrl.numberOfSegments*em;
CGFloat segCtrlHeight = segCtrlRect.size.height + em;
CGFloat segmentY = segCtrl.frame.origin.y - (segCtrlHeight - segCtrlRect.size.height)/2;
segCtrl.frame = CGRectMake(segCtrl.frame.origin.x, segmentY, segCtrlWidth, segCtrlHeight);
}