2013-10-02 5 views
18

Я хочу дать следующий аспект к UISegmentedControl:UISegmentedControl границы

enter image description here

Обратите внимание на серый вид фона и белый фон сегментированной управления не выбранного элемента.

Но, если я дам белый фон в моем UISegmentedControl, я получаю следующее:

enter image description here

Обратите внимание на белый квадрат углы вокруг UISegmentedControl. Что я должен сделать, чтобы избежать этих квадратных углов?

Спасибо заранее,

EDIT: Если изменить радиус скругления углов слоя UISegmentedControl, поскольку предложенный onegray, результат лучше, но не идеально (обратите внимание на белую линию справа):

enter image description here

+0

Вы можете установить 'segmented.backgroundColor = [UIColor clearColor];' –

+0

@Viruss MCA: Спасибо за ваш комментарий, но, в этом случае, фон за «Тратадом» как "показано серым, а не белым. – neutrino

+0

Вы также можете использовать два UIButtons вместо UISegmentedControl в качестве альтернативного решения. – Engnyl

ответ

10

Если это должно работать на всех UISegmentedControls это немного хлопот. Проблема в iOS7 1 pt. граница между двумя сегментами не учитывает размер сегмента. Например. если рамка вашего UISegmentedControl - 320 pt. вам нужно удалить 1 pt. и деление на 2. И (320-1)/2 составляет 159,5. iOS составляет это значение до 159 пт. И вы получите 1 pt. границы и два 159 пт. сегменты. Это 319, а не 320. Следовательно, 1pt. линии справа от вашего сегментаемого управления.

Существует способ расчета размера «фактического» (размер рендеринга на экране) сегментаризованного управления. С этой шириной вы можете добавить UIView с закругленными углами ниже UISegmentedControl. Этот код должен работать для всех конфигураций, даже если у вас есть сегменты вручную размера в вашем segmentedControl:

- (UIView *)addBackgroundViewBelowSegmentedControl:(UISegmentedControl *)segmentedControl { 
    CGFloat autosizedWidth = CGRectGetWidth(segmentedControl.bounds); 
    autosizedWidth -= (segmentedControl.numberOfSegments - 1); // ignore the 1pt. borders between segments 

    NSInteger numberOfAutosizedSegmentes = 0; 
    NSMutableArray *segmentWidths = [NSMutableArray arrayWithCapacity:segmentedControl.numberOfSegments]; 
    for (NSInteger i = 0; i < segmentedControl.numberOfSegments; i++) { 
     CGFloat width = [segmentedControl widthForSegmentAtIndex:i]; 
     if (width == 0.0f) { 
      // auto sized 
      numberOfAutosizedSegmentes++; 
      [segmentWidths addObject:[NSNull null]]; 
     } 
     else { 
      // manually sized 
      autosizedWidth -= width; 
      [segmentWidths addObject:@(width)]; 
     } 
    } 

    CGFloat autoWidth = floorf(autosizedWidth/(float)numberOfAutosizedSegmentes); 
    CGFloat realWidth = (segmentedControl.numberOfSegments-1);  // add all the 1pt. borders between the segments 
    for (NSInteger i = 0; i < [segmentWidths count]; i++) { 
     id width = segmentWidths[i]; 
     if (width == [NSNull null]) { 
      realWidth += autoWidth; 
     } 
     else { 
      realWidth += [width floatValue]; 
     } 
    } 

    CGRect whiteViewFrame = segmentedControl.frame; 
    whiteViewFrame.size.width = realWidth; 

    UIView *whiteView = [[UIView alloc] initWithFrame:whiteViewFrame]; 
    whiteView.backgroundColor = [UIColor whiteColor]; 
    whiteView.layer.cornerRadius = 5.0f; 
    [self.view insertSubview:whiteView belowSubview:segmentedControl]; 
    return whiteView; 
} 

Пожалуйста, позаботьтесь кадра изменяет себя.

Смотрите этот снимок экрана, чтобы увидеть разницу между двумя элементами управления. Все фреймы составляют 280 пт. широкий.

Из-за формулы UISegmentedControl использует первый контрольный размер фактического размера 278 пт. И реальный размер второго - 279 пт.

enter image description here


Проблема заключается в том, что это каким-то образом зависит от реализации UISegmentedControl. Apple может, например, изменить реализацию, так что будет отображаться сегментная ширина, которая заканчивается на 0,5 балла. Они могли легко сделать это на сетчатых дисплеях.

Если вы используете этот код, вы должны проверить свое приложение на новых версиях iOS как можно раньше. Мы полагаемся на детали реализации, и они могут меняться каждый день. К счастью, ничего плохого не происходит, если они меняют реализацию. Это будет выглядеть не очень хорошо.

+0

Большое спасибо! Он работает нормально. И вы дали большое объяснение. – neutrino

16

Установка _segmentedControl.layer.cornerRadius = 5; может помочь.

Update: Более сложный клип Прямоугольник, чтобы избавиться от 1px правого пространства:

CAShapeLayer* mask = [[CAShapeLayer alloc] init]; 
    mask.frame = CGRectMake(0, 0, _segmentedControl.bounds.size.width-1, _segmentedControl.bounds.size.height); 
    mask.path = [[UIBezierPath bezierPathWithRoundedRect:mask.frame cornerRadius:4] CGPath]; 
    _segmentedControl.layer.mask = mask; 

Обновления: Matthias Bauch предоставил хорошее объяснение, почему на правой стороне UISegmentedControl появляется этот пробел. Таким образом, самый простой способ удалить его - сделать сегменты фиксированного размера и настроить их для правильной ширины.

+0

Благодарим вас за ответ. В результате результат лучше, но далек от совершенства. См. Изображение в моем оригинальном посте. – neutrino

+0

Еще раз спасибо. Наконец, я пошел с ответом Маттиаса, но ты мне очень помог. Я тестировал ваше решение, и оно работает для меня тоже. – neutrino

+0

Отличное решение. Благодаря!!! –

2

Я знаю, что это своего рода хак, но вы можете просто использовать округленный UIView с белым фоном, расположенным чуть ниже - и выровненным с - сегментированным элементом управления, за исключением ширины, которая должна быть равна ширине исходного элемента управления минус 1 .

Результат: Segmented Control with White Background

+0

Если вы используете Autolayout, вы можете закрепить «фоновый вид», чтобы соответствовать ширине/высоте и т. Д. SegmentControl, поэтому не нужно настраивать с минусом 1. И, конечно, вы можете использовать атрибуты времени выполнения, чтобы также установить cornerRadius фонового представления – wuf810

0

Только до уточнить отличный ответ Маттиаса Бауха. Вам нужно установить возвращаемый вид как подвид с точки зрения (которую мы называем yourMainView), где у вас есть свой сегментированный контроль:

UIView *segmControlBackground = [self addBackgroundViewBelowSegmentedControl:yourSegmentedControl]; 
[yourMainView addSubview:segmControlBackground]; 



И вам нужно, конечно, объявить новый метод в файле заголовка (.h):

- (UIView *)addBackgroundViewBelowSegmentedControl:(UISegmentedControl *)segmentedControl; 
Смежные вопросы