Как отключить сообщение "highlight subviews" для UIView/UIViewController в SDK для iOS?

Я хочу использовать выделение по умолчанию на UITableViewCell, когда он прослушивается. Тем не менее, я не хочу, чтобы пользовательские подзаголовки (и их дочерние объекты) получали сообщение для обновления своих выделенных состояний и, следовательно, нарушали свойство backgroundColor.

Edit
Под "subview" я подразумеваю любой подкласс UIView, а не только UITableViewCell s.

Возможно, эта гипотетическая ситуация лучше сформулирует то, что я ищу. У меня есть один UITableViewCell. Назовите его c. Затем я добавляю один UIView (назовем его v) в качестве подзаголовка c. Когда я нажимаю c, я хочу, чтобы c стал выделен (стандартный синий фон с белым цветом шрифта), но я не хочу, чтобы v стал подсвечен. Как это сделать?

Ответ 1

Прежде всего, UITableView перечисляет все подзапросы и отправляет их выделенные сообщения.

Таким образом, даже если вы положите UILabel в своем представлении, независимо от того, насколько он глубок, он пересекает все представления (используя свойство subviews).

Одно решение может быть (это IOS4 +), переопределяя свойство subviews и функцию выделения чит-таблицы, что у нас нет подзонов. Для этого нам нужно определить вызывающего, и если это метод подсветки tableview, мы не должны возвращать никакие подпункты вообще.

Мы можем создать простой подкласс UIView и переопределить subviews, как показано ниже.

- (NSArray *)subviews{
    NSString* backtrace = [NSString stringWithFormat: @"%@",[NSThread callStackSymbols]];
    if ([backtrace rangeOfString:@"_updateHighlightColorsForView"].location!=NSNotFound)
        return [super subviews];   

    return [[NSArray new] autorelease];
}
  • callStackSymbols доступен после IOS4 +
  • _updateHighlightColorsForView - это метод UITableView, отвечающий за выделение всех дочерних элементов

Ответ 2

У меня есть класс, который наследует от UITableViewCell, поэтому я исправил его переопределение setSelected:animated следующим образом:

   - (void)setSelected:(BOOL)selected animated:(BOOL)animated
   {
       [super setSelected:selected animated:animated]; 
       //Reset highlighted status to all the childs that i care for.
       [self.someChild setHighlighted:NO];
       [self.someOtherChild setHighlighted:NO];
   }

Ответ 4

Я решил эту проблему, переопределив -(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated как это (работает только если subview является подклассом UIControl):

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {

    BOOL subviewWasEnabled = mySubview.enabled; //check if the view is enabled
    mySubview.enabled = NO; //disable it anyways

    [super setHighlighted:highlighted animated:animated];

    mySubview.enabled = subviewWasEnabled; //enable it again (if it was enabled)
}

Ответ 5

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

Так как я подчеркиваю уважение к изображениям, я закончил с помощью UIImageView подал весь кадр моего UIView и присвоил ему пустое изображение и нарисовал остальную часть представления над UIImageView. Ваш UIView будет по-прежнему выделен, но вы не сможете его увидеть, потому что будет пустое изображение выше!

Надеюсь, это поможет, я знаю, что это, вероятно, не самый лучший подход, но дал мне результаты, которые я хотел

Ответ 6

Переопределить метод -(void)setHighlighted:(BOOL)highlight; в подклассе UIControl, чтобы он ничего не делал. В случае подкласса UIButton вы можете сделать:

- (void)setHighlighted:(BOOL)highlighted {
    return;
}

Ответ 7

Я не хотел, чтобы какое-либо из подзонов было выделено. Мое решение состояло в том, чтобы установить selectionstyle в UITableViewCellSelectionStyleNone и имитировать поведение выбора по умолчанию следующим образом (переопределяя setSelected в пользовательском подклассе UITableViewCell):

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

    int backgroundViewTag = 888;
    UIView *backgroundView = [self viewWithTag:backgroundViewTag];

    if (selected) {
        if (!backgroundView) {
            backgroundView = [[[UIView alloc] initWithFrame:self.bounds] autorelease];
            backgroundView.tag = backgroundViewTag;
            backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
            backgroundView.backgroundColor = [UIColor blueColor];
            backgroundView.alpha = 0.0;
            [self insertSubview:backgroundView atIndex:0];
        }

        if (animated) {
            [UIView animateWithDuration:0.5 animations:^{
                backgroundView.alpha = 1.0;
            }];
        } else {
            backgroundView.alpha = 1.0;
        }
    } else if (backgroundView) {
        if (animated) {
            [UIView animateWithDuration:0.5 animations:^{
                backgroundView.alpha = 0.0;
            } completion:^(BOOL finished) {
            }];
        } else {
            backgroundView.alpha = 0.0;
        }
    }
    [super setSelected:selected animated:animated];
}

Ответ 8

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

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

Не уверен, что он работает, можете ли вы описать subviews больше.

Ответ 9

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

Ответ 10

Может быть, если вы подклассифицируете ваш subview и переопределите метод setHighlighted, чтобы ничего не делать или переопределить выделенный метод для возврата всегда NO.

Но UIView не имеет выделенного состояния, какие дочерние элементы UIView вы добавляете в свою ячейку?

Ответ 11

Итак, возможно, что-то вроде этого:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

m_colors = [[NSMutableArray alloc] init];

for (UIView *view in [cell.contentView subviews]) {
    [m_colors addObject:view.backgroundColor];
}

return indexPath;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

for (int x = 0; x < [m_colors count]; ++x) {
    [[[cell.contentView subviews] objectAtIndex:x] setBackgroundColor:[m_colors objectAtIndex:x]];
}

[m_colors release];
m_colors = nil;
}

Ответ 12

Просто разместите свои представления внутри UIButton, и они не обновляются при подсветке. Вы не можете сделать это с помощью xib раскадровки только в runtime.

UIButton *button = [[UIButton alloc] initWithFrame:0, 0, cellWidth, cellHeight];
[button addSubview:anyView]; // This view don't change his background color
[cell addSubview:button];