selectedBackgroundView изменяет подпредставления contentView

Я использую пользовательские backgroundView и selectedBackgroundView для подкласса UITableViewCell. Эти ячейки находятся в сгруппированной таблице, поэтому я устанавливаю фон и выбираю фон как UIImageViews на основе строки ячейки в cellForRowAtIndexPath:.

У меня проблема в том, что когда ячейка выбрана, ее selectedBackgroundView изменяет содержимое contentView. Например, после выбора и/или выделения ячейки UILabel в contentView изменяется на backgroundColor, а UIView, используемый в качестве разделителя ячеек, не виден.

Перед выбором: Перед выбором/выделениемПосле выбора: После выбора/выделения

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

  • Примечание. Поскольку это сгруппированное табличное представление, я установил разные backgroundViews и selectedBackgroundViews с UIImageViews, чтобы учесть закругленные углы в верхней и нижней ячейках в разделе в cellForRowAtIndexPath:, но у меня та же проблема при использовании по умолчанию UITableViewSelectionStyleBlue.

Редактировать 1:

Согласно ответу an0, я отменил setHighlighted:animated:. Я не уверен, насколько надежна реализация, но этот подход помог сохранить свойства highlighted и backgroundColor подвидов:

NSArray *recursiveAllSubviews = [self recursiveValueForKey:@"subviews"]; // Uses MTRecursiveKVC Cocoapod
NSArray *backgroundColors = [recursiveAllSubviews valueForKey:@"backgroundColor"];
[super setHighlighted:highlighted animated:animated];
if (highlighted) {
    [recursiveAllSubviews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger index, BOOL *stop){
        if ([view respondsToSelector:@selector(setHighlighted:)]) {
            [view setValue:[NSNumber numberWithBool:NO] forKey:@"highlighted"];
        }
        id possiblyNull = [backgroundColors objectAtIndex:index];
        if (possiblyNull != [NSNull null]) {
            view.backgroundColor = possiblyNull;
        }
    }];
}

person MaxGabriel    schedule 22.01.2013    source источник
comment
Ах, это, вероятно, связано с тем, что содержимое выбирается автоматически, если подпредставление реализует (если необходимо) методы доступа для выделенного свойства.   -  person MaxGabriel    schedule 23.01.2013


Ответы (4)


UITableViewCell автоматически делает две вещи при выделении/выборе:

  1. Установите для всех его подпредставлений backgroundColor чистый цвет (прозрачный).
  2. Выделите все подпредставления, которые можно выделить, например, UIImageView.

Чтобы предотвратить первую проблему, вы должны переопределить эти два метода в вашем подклассе UITableViewCell:

- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
    [super setHighlighted:highlighted animated:animated];
    if (highlighted) {
        // Recover backgroundColor of subviews.
    }
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
    if (selected) {
        // Recover backgroundColor of subviews.
    }
}
person an0    schedule 22.01.2013
comment
Потрясающий. Мой разделитель ячеек был реализован с использованием свойства backgroundColor, что объясняет, почему он также исчез. - person MaxGabriel; 23.01.2013
comment
Я тоже мог догадаться, потому что я делал подобные вещи :) - person an0; 23.01.2013
comment
Если я хочу остановить поведение 1. и 2., лучше ли мне переопределить методы setHighlighted:animated: и setSelected:animated:, не вызывать super и реализовать методы самостоятельно? Если нет хорошего способа выполнить шаг «восстановить backgroundColor», о котором вы упомянули. - person MaxGabriel; 23.01.2013
comment
Хорошо, я придумал решение и добавил код к своему вопросу. - person MaxGabriel; 23.01.2013
comment
Четко и лаконично. Хороший ответ. - person Tom Redman; 30.10.2013
comment
Я пришел сюда в поисках решения другой, но связанной проблемы, но ваш ответ и комментарий @MaxGabriel прояснили, что моя настоящая проблема заключалась в том, что фон представления стал прозрачным. Спасибо! - person sumizome; 25.04.2014
comment
UIButton не выделяется при выборе ячейки. Я думаю, что выделены не все подвиды, кроме UIControl. - person Ge Liu; 07.04.2015
comment
Это работает, но все еще отсутствует во время возврата к tableViewController. Есть идеи? - person JZAU; 24.05.2016

установить cell.selectionStyle = UITableViewCellSelectionStyleNone и переопределить

- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
  if(highlighted) {
    self.contentView.backgroundColor = colorYouWantWhenHighlighted;
  } else {
    self.contentView.backgroundColor = colorYouWantWhenUnhighlighted;
  }
}
person nyus2006    schedule 17.12.2013
comment
Я сделал что-то похожее на это, но вместо того, чтобы переопределить метод (потребовался бы новый класс и т. д.), я просто вручную изменил фон ячейки в tableView:didSelectRowAtIndexPath:. - person Krynble; 09.01.2014
comment
Я предполагаю, что когда вы нажимаете на ячейку, приложение сразу же переводит вас на следующий экран. Я сомневаюсь, что ваш метод работает для состояния выделения (например, положите палец на ячейку и удерживайте, а затем перетащите за пределы ячейки, ячейка не должна быть выделена). Вы можете это проверить? - person nyus2006; 10.01.2014
comment
ты был почти там. Правильный метод не setHighlighted, а setSelected. - person Duck; 10.06.2020

В моем случае у меня было две кнопки в моем UITableViewCell, цвета фона которых очищались. Эти кнопки имели тип GrayButton, пользовательский класс, который я написал, производный от UIButton. Вместо переопределения методов UITableViewCell я переопределил метод setBackgroundColor: GrayButton:

- (void)setBackgroundColor:(UIColor *)backgroundColor
{
    if (backgroundColor != [UIColor clearColor]) {
        [super setBackgroundColor:backgroundColor];
    }
}
person NathanAldenSr    schedule 18.11.2013

В моем случае я переключился на contentView, и он работает намного лучше.

UIColor *backgroundColor = selected ? [UIColor redColor] : [UIColor clearColor];
self.contentView.backgroundColor = backgroundColor;

вместо замены selectedBackgroundView

UIView *selectionColor = [[UIView alloc] init];
selectionColor.backgroundColor = selected ? [UIColor redColor] : [UIColor clearColor];;
self.selectedBackgroundView = selectionColor;
[selectionColor release];

теперь проблема видна только в том случае, если ячейка, которую вы нажимаете и начинаете прокрутку, не является выбранной ячейкой.

person Dani.Rangelov    schedule 20.03.2014