Почему UICollectionViewCell UICollectionView не выделяется при прикосновении пользователя?

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

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

Однако я понимаю, что когда пользователь касается ячейки, она должна выделяться (синим цветом), а затем подсветка должна исчезать, когда пользователь поднимает палец. Этого не происходит. Любые мысли о том, почему?

Вот соответствующий код:

В источнике данных UICollectionView:

@implementation SplitCheckViewCollection

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellIdentifier = @"ReceiptCellIdentifier";
    SplitCheckCollectionCell *cell = (SplitCheckCollectionCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
    cell.cellName.text = [NSString stringWithFormat:@"%@%i",@"#",indexPath.row+1];

    return cell;
}

В реализации UICollectionViewCell:

@implementation SplitCheckCollectionCell

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"SplitCheckCollectionCell" owner:self options:nil];

        if ([arrayOfViews count] < 1) {
            return nil;
        }

        if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) {
            return nil;
        }

        self = [arrayOfViews objectAtIndex:0];    
    }
    return self;
}

person IkegawaTaro    schedule 31.01.2013    source источник
comment
из руководства разработчика. Если свойство selectedBackgroundView ячейки содержит допустимое представление, представление коллекции показывает это представление, когда ячейка выделена или выбрана.   -  person topwik    schedule 07.06.2013


Ответы (9)


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

Подробности описаны в Руководство по программированию CollectionView.

person SAE    schedule 31.01.2013
comment
таким образом, при прикосновении пользователя состояние выделения не переходит автоматически в ДА? или он переходит в ДА, но внешний вид не меняется автоматически? - person IkegawaTaro; 01.02.2013
comment
Для него установлено значение YES, но внешний вид не изменяется фреймворком. Вы можете перехватить, например. через метод делегата collectionView:didHighlightItemAtIndexPath: - person SAE; 01.02.2013
comment
developer.apple.com/library/ios/documentation/WindowsViews/ это может быть новое местоположение документа. - person Ahmet Akkök; 16.05.2016

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

Я создал ячейку в раскадровке, и в представлении коллекции по умолчанию установлено «задерживает касание содержимого». Я снял этот флажок, и он мгновенно отобразился, когда палец коснулся экрана.

Я использую пользовательскую процедуру рисования, которая проверяет значение isHighlighted. Вам также необходимо переопределить setHighlighted в пользовательской ячейке, как показано ниже, иначе процедура рисования никогда не будет вызвана.

-(void)setHighlighted:(BOOL)highlighted
{
    [super setHighlighted:highlighted];
    [self setNeedsDisplay];
}
person Ajaxharg    schedule 01.02.2013
comment
Спасибо за подсказку о «задержке касаний контента»! У меня была такая же проблема с быстрым тапом. - person IkegawaTaro; 03.02.2013
comment
Как и Икегава, спасибо за подсказку о «задержке касаний контента». - person Matt Mc; 21.12.2013

Есть 2 метода делегата, которые вы должны реализовать:

- (void)collectionView:(UICollectionView *)colView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)colView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath;

Полный код выделения ячейки представления коллекции с анимацией:

- (void)collectionView:(UICollectionView *)colView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
     UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
     //set color with animation
    [UIView animateWithDuration:0.1
                      delay:0
                    options:(UIViewAnimationOptionAllowUserInteraction)
                 animations:^{
                     [cell setBackgroundColor:[UIColor colorWithRed:232/255.0f green:232/255.0f blue:232/255.0f alpha:1]];
                 }
                 completion:nil];
 }

- (void)collectionView:(UICollectionView *)colView  didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
    //set color with animation
    [UIView animateWithDuration:0.1
                      delay:0
                    options:(UIViewAnimationOptionAllowUserInteraction)
                 animations:^{
                     [cell setBackgroundColor:[UIColor clearColor]];
                 }
                 completion:nil ];
}
person ashakirov    schedule 12.08.2014

Вам необходимо реализовать UICollectionViewDataSource, если вы хотите иметь эффект выделения и отмены выделения при касании и отпускании касания.

вот пример кода

#pragma mark - UICollectionView Datasource

 - (void)collectionView:(UICollectionView *)colView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
 UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
 cell.contentView.backgroundColor = [UIColor colorWithRed:235/255.0f green:236/255.0f blue:237/255.0f alpha:.5];
 }

 - (void)collectionView:(UICollectionView *)colView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath {
 UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
 cell.contentView.backgroundColor = nil;
 }
person Basil Mariano    schedule 09.07.2015
comment
Это хорошо для ячейки представления коллекции по умолчанию, но не будет работать для пользовательской ячейки UICollectionViewCell. Xcode покажет ошибку. - person Anish Kodeboyina; 07.09.2017

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

UIView* selectedBGView = [[UIView alloc] initWithFrame:self.bounds];
selectedBGView.backgroundColor = [UIColor redColor];
self.selectedBackgroundView = selectedBGView;

Из «Управление визуальным состоянием для выбора и выделения»... Представления коллекции поддерживают выбор одного элемента по умолчанию и могут быть настроены для поддержки выбора нескольких элементов или вообще для отключения выбора. Представление коллекции обнаруживает нажатия внутри своих границ и соответствующим образом выделяет или выбирает соответствующую ячейку. По большей части представление коллекции изменяет только свойства ячейки, чтобы указать, что она выбрана или выделена; это не меняет внешний вид ваших ячеек, за одним исключением. Если свойство selectedBackgroundView ячейки содержит допустимое представление, представление коллекции показывает это представление, когда ячейка выделена или выбрана.

person troppoli    schedule 28.10.2013

Как указывает SAE, вам придется вручную сделать это в выделенной ячейке. Самый простой способ, который я нашел, - это использовать методы tableview didHighlightRowAtIndexPath и didUnhighlightRowAtIndexPath, которые устанавливают логическое значение, «выделенное» в вашем экземпляре UICollectionCell, а затем переопределяют это свойство в подклассе класса UICollectionCell. Прелесть этого в том, что анимация уже есть для вас. Вы также можете сделать то же самое в ситуации UITableView/UITableViewCell.

Итак, в вашем UICollectionView с помощью метода UICollectionViewDelegate:

func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath) {
    collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: UICollectionViewScrollPosition.None)
}

func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath) {
    collectionView.deselectItemAtIndexPath(indexPath, animated: true)
}

Затем в вашем подклассе UICollectionViewCell добавьте следующее:

override var highlighted:Bool{
    didSet{
        println("Highlighted is set \(highlighted)")
        if(highlighted == true){
            self.backgroundColor = UIColor.redColor()
        }else{
            self.backgroundColor = UIColor.blueColor()
        }
    }
}
person Tim    schedule 02.07.2015
comment
Может ли кто-нибудь ответить, почему они проголосовали за этот ответ? было бы неплохо получить отзыв, а не просто минус - person Tim; 15.07.2015
comment
Это не работает. Все, что вы установите для ячейки, будет временным, поскольку ячейку можно будет использовать повторно, когда вы прокручиваете ее за пределы экрана. - person worthwords; 02.12.2016

вы можете попробовать этот код:

- (void)collectionView:(UICollectionView *)colView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor blueColor];
}

а также

- (void)collectionView:(UICollectionView *)colView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell* cell = [colView cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = nil;
}
person Ha cong Thuan    schedule 02.07.2015

Мы можем создать собственный эффект подсветки и удаления подсветки для collectionViewCell, добавляя и удаляя временный view с фоновым цветом следующим образом:

 -(void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
    
    {
        
         UICollectionViewCell *collectionViewCell = (UICollectionViewCell *)  
                            [collectionView cellForItemAtIndexPath:indexPath];
           
     UIView *tapHighlightView = (UIView*)[collectionViewCell.contentView 
                                  viewWithTag:10];
    
     if (!tapHighlightView) {
    
                tapHighlightView = [[UIView alloc] 
                        initWithFrame:collectionViewCell.contentView.frame];
                tapHighlightView.backgroundColor =[UIColor blackColor alpha:0.4];
                tapHighlightView.tag = 10;
                [collectionViewCell.contentView addSubview:tapHighlightView];
            }
    }
    
    -(void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath{
    
        UICollectionViewCell *collectionViewCell = (UICollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
        UIView *tapHighlightView = (UIView*)[collectionViewCell.contentView viewWithTag:10];
        if (tapHighlightView != nil) {
            [tapHighlightView removeFromSuperview];
        }
    }
person KSR    schedule 12.08.2016

Если вы хотите изменить визуальные эффекты, вы можете установить выбранную ячейку в didHighlightItemAtIndexPath и отменить выбор в didHighlightItemAtIndexPath следующим образом:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    [collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:NO];
}

- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    [collectionView deselectItemAtIndexPath:indexPath animated:YES];
}
person Frank    schedule 14.05.2014