UISegmentedControl не учитывает разделительные изображения, установленные для UIControlStateDisabled - PullRequest
5 голосов
/ 12 марта 2012

Я использую новый UIAppearance API в iOS 5 для стилизации UISegmentedControl с пользовательской графикой. Мне нужно иметь возможность периодически отключать некоторые сегменты во время выполнения, но методы UIAppearance, похоже, не позволяют мне установить изображение делителя для состояния UIControlStateDisabled.

Я звоню:

[[UISegmentedControl appearance] setDividerImage:disabledSelectedImage
                                    forLeftSegmentState:UIControlStateDisabled
                                    rightSegmentState:UIControlStateSelected
                                    barMetrics:UIBarMetricsDefault];

, где disabledSelectedImage - изображение с изменяемым размером с этого ресурса:

disabled-selected-image

Тем не менее, когда я отключаю левый сегмент ([UISegmentedControl setEnabled:forSegmentAtIndex:]), результат таков:

UISegmentedControl UI glitch

Вы можете ясно видеть, что UISegmentedControl по умолчанию использует разделительное изображение UIControlStateNormal - UIControlStateNormal.

Кажется, я очень рад установить фоновое изображение, используя UIControlStateDisabled

[[UISegmentedControl appearance] setBackgroundImage:disabledImage
                                    forState:UIControlStateDisabled
                                    barMetrics:UIBarMetricsDefault];

(и учитывает изображение, которое я предоставляю в отключенном состоянии), но не изображение делителя. Кто-нибудь сталкивался с этим или нашел решение?

Ответы [ 6 ]

3 голосов
/ 12 марта 2012

Я решил, что это ошибка iOS, и подал радар в Apple.Мое решение проблемы на данный момент состоит в том, чтобы удалить сегменты, а не отключать их.

1 голос
/ 01 сентября 2012

Немного уродливый обходной путь, но мне удалось исправить это следующим образом, пока apple не исправит это сам.

Сначала вам нужно создать подкласс UISegmentedControl и добавить следующее:

@implementation MJSegmentedControl

- (void)layoutSubviews
{
    [super layoutSubviews];
    NSInteger cachedIndex = self.selectedSegmentIndex;
    self.selectedSegmentIndex = 0;
    self.selectedSegmentIndex = cachedIndex;
}

@end
0 голосов
/ 02 июня 2013

Существует довольно простой способ сделать это. Текущее поведение, очевидно, является ошибкой, поэтому это не идеальное решение, а просто обходной путь, который прекрасно работает. А именно, используйте дополнительный UIView в качестве «отключенной визуальной подсказки».

Общие шаги:

  1. Добавить UIView в качестве родственного элемента в UISegmentedControl. Убедитесь, что UIView находится перед UISegmentedControl
  2. Примените желаемый цвет и прозрачность к UIView в соответствии со скином вашего приложения
  3. Переместите UIView так, чтобы оно находилось точно над UISegmentedControl
  4. Сформируйте UIView, чтобы иметь точный размер UISegmentedControl
  5. Применить закругленный угол к UIView, чтобы отразить точную форму UISegmentedControl

Когда предполагается отключить UISegmentedControl, просто отобразите UIView и отключите взаимодействие с пользователем на UISegmentedControl.

Когда предполагается включить UISegmentedControl, просто скройте UIView и включите взаимодействие с пользователем в UISegmentedControl.

В обоих случаях не изменяйте свойство UISegmentedControl.enabled.

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

Вот как выглядит мой пользовательский сегментный элемент управления при применении этого решения:

Включено сегментированное управление

enabled segmented control

«Отключено» Сегментированное управление

disabled segmented control

Вот некоторые интересные фрагменты кода:

Форма UIView для соответствия UISegementedControl (конфигурация времени загрузки)

  UISegmentedControl* segmentedControl = ...
  //Segmented Control disabled visual cue view
  UIView* view = ...

  //Step #2       
  view.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.6];

  //Step #3 and #4
  view.frame = segmentedControl.frame;

  //Step #5
  view.layer.cornerRadius = 5
  view.clipsToBounds = YES;

  //Ensure this is disabled by default
  view.userInteractionEnabled = NO;

Включить / «Отключить» UISegementedControl (изменение состояния среды выполнения)

BOOL segmentedControlEnabled = ...

if(segmentedControlEnabled) {
  segmentedControl.userInteractionEnabled = YES;
  view.hidden = YES;    
} else {     
  segmentedControl.userInteractionEnabled = NO;
  view.hidden = NO;
}

Вот и все.

-

0 голосов
/ 11 апреля 2013

В соответствии с предложением Фернандо в этой теме: Настройка UISegmentedControl в iOS 5

Вы можете попытаться отправить ваши настройки UISegmentedControl в основную очередь через:

dispatch_async(dispatch_get_main_queue(),^{
    // disable part of the segmented control
    [self.eventScopeSegmentedControl setEnabled:NO forSegmentAtIndex:2];
});

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

Я добавил еще один уродливый хак, чтобы сделать этот вызов в viewWillAppear (после вызова super: viewWillAppear)с флагом (установленным из viewWillLoad), чтобы убедиться, что это выполняется только один раз.

0 голосов
/ 11 января 2013

У меня была такая же проблема, и это действительно похоже на ошибку. Однако я нашел решение (обходной путь).

Я использовал файл XIB с контроллером. В файле XIB был просто размещен сегментированный элемент управления, и все настройки были выполнены методом -viewDidLoad.

Затем я создал подкласс UIView, который представлял весь вид в XIB. Это позволило переместить весь код настройки представления в метод -awakeFromNib этого подкласса UIView. После перемещения этого кода изображения делителя были установлены правильно.

0 голосов
/ 12 марта 2012

У меня еще не было необходимости использовать элементы управления внешним видом iOS 5, но если ничего не помогло, вы могли бы добавить изображение с изменяемым размером в качестве дочернего элемента сегментированного элемента управления, чтобы скрыть уродство. Это взлом, но он может работать и будет относительно совместим. Просто убедитесь, что вы правильно настроили маски автоматического изменения размера.

...