UISegmentedControl не учитывает изображения разделителей, установленные для UIControlStateDisabled.

Я использую новый 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 сбой

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

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

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

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


person Ell Neal    schedule 12.03.2012    source источник
comment
Это похоже на ошибку. Я думаю, вам следует отправить его на bugreport.apple.com.   -  person jfortmann    schedule 12.03.2012
comment
@jfortmann Я думаю, вы правы, я изменил поток, чтобы удалить сегменты вместо их отключения. Кажется, в UIAppearance API для UISegmentedControl довольно много ошибок.   -  person Ell Neal    schedule 12.03.2012


Ответы (6)


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

person Ell Neal    schedule 12.03.2012
comment
Я сделал то же самое ранее на этой неделе. Рад видеть, что я не единственный. - person Cory Kilger; 14.03.2012
comment
@CoryKilger Я тоже заметил ваш отчет при создании этого сегментированного элемента управления, но, к счастью, это не повлияло на меня, потому что мне не нужно было сначала выбирать второй сегмент. Я опубликую ваш через радар, так что, надеюсь, мы привлечем больше внимания. - person Ell Neal; 14.03.2012

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

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

@implementation MJSegmentedControl

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

@end
person choise    schedule 01.09.2012

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

person TigerCoding    schedule 12.03.2012
comment
Я планирую использовать настраиваемые сегментированные элементы управления во всем приложении, возможно, с разным количеством сегментов/позиций и т. д. Так что, к сожалению, я не думаю, что это сработает для меня. - person Ell Neal; 12.03.2012
comment
Почему бы не создать свой собственный подкласс UISegmentedControl, который автоматически добавляет изображение с изменяемым размером? - person TigerCoding; 13.03.2012

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

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

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

person Misha Karpenko    schedule 11.01.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), чтобы гарантировать, что он выполняется только один раз.

person Henry Green    schedule 10.04.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 лайнером после того, как вы добавите это в метод сегментированного управления configure.

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

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

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

Отключенный сегментированный элемент управления

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

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

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

  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;

Включить/отключить UISementedControl (изменение состояния во время выполнения)

BOOL segmentedControlEnabled = ...

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

Вот и все.

-

person infinite-loop    schedule 02.06.2013