Подтвердить что ты не робот

Ограничения UISegmentedControl

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

enter image description here

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

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

enter image description here

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

Заранее спасибо,

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

enter image description here

4b9b3361

Ответ 1

Если это должно работать для всех 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. Этот код должен работать для всех конфигураций, даже если у вас есть сегменты с ручным размером в сегменте управления:

- (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 пт.

введите описание изображения здесь


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

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

Ответ 2

Настройка _segmentedControl.layer.cornerRadius = 5; может помочь.

Обновление: более сложный клип, чтобы избавиться от правого пространства 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;

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

Ответ 3

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

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

Ответ 4

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

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



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

- (UIView *)addBackgroundViewBelowSegmentedControl:(UISegmentedControl *)segmentedControl;