【问题标题】:Why UICollectionView's UICollectionViewCell is not highlighting on user touch?为什么 UICollectionView 的 UICollectionViewCell 没有在用户触摸时突出显示?
【发布时间】:2013-01-16 05:14:26
【问题描述】:

我有一个由自定义 UICollectionViewCell 子类组成的 UICollectionView。通过触发此方法,单元格正在正确显示并正确响应用户的触摸:

- (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;
}

【问题讨论】:

  • 来自开发指南。如果单元格的 selectedBackgroundView 属性包含有效视图,则集合视图会在单元格突出显示或选中时显示该视图。

标签: ios objective-c uicollectionview


【解决方案1】:

我们可以通过添加和删除带有一些背景颜色的临时view,在collectionViewCell 上创建自己的高亮和取消高亮效果,如下所示:

 -(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];
        }
    }

【讨论】:

    【解决方案2】:

    该类只告诉您高亮状态,但不会改变视觉外观。您必须以编程方式执行此操作,例如改变单元格的背景。

    详情请见CollectionView Programming Guide

    【讨论】:

    • 所以,在用户触摸时,高亮状态不会自动变为“是”?还是选择“是”但视觉外观没有自动变化?
    • 设置为YES,但框架不改变视觉外观。您可以拦截例如通过委托方法collectionView:didHighlightItemAtIndexPath:
    【解决方案3】:

    您需要实现 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;
     }
    

    【讨论】:

    • 这适用于默认的集合视图单元格,但这不适用于自定义 UICollectionViewCell。 Xcode 会显示错误。
    【解决方案4】:

    正如 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()
            }
        }
    }
    

    【讨论】:

    • 有人能回答他们为什么不赞成这个答案吗?最好有一些反馈,而不仅仅是投反对票
    • 它不起作用。您在单元格上设置的任何内容都将是暂时的,因为当您将其滚动到屏幕外时,可以重复使用该单元格。
    【解决方案5】:

    你可以试试这个代码:

    - (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;
    }
    

    【讨论】:

      【解决方案6】:

      您应该实现 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 ];
      }
      

      【讨论】:

        【解决方案7】:

        如果您想更改视觉效果,您可以在 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];
        }
        

        【讨论】:

          【解决方案8】:

          您可以通过将这些线条添加到 UICellView 的设置中来获得要绘制的亮点。

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

          来自“管理选择和突出显示的视觉状态”... 集合视图默认支持单项选择,可以配置为支持多项选择或完全禁用选择。集合视图检测其边界内的点击并相应地突出显示或选择相应的单元格。在大多数情况下,collection view 只修改单元格的属性以表明它被选中或突出显示; 它不会改变单元格的视觉外观,但有一个例外。如果单元格的 selectedBackgroundView 属性包含有效视图,则集合视图会在单元格突出显示或选中时显示该视图。

          【讨论】:

            【解决方案9】:

            正如 SAE 所说,你必须在子类中自己做。我刚刚遇到的另一个问题是,当点击一个单元格时,如果按下并按住该单元格,它将接收高亮并重绘。但是,如果快速点击,重绘就不会发生。

            我在情节提要中创建了单元格,并且集合视图默认勾选了“延迟内容触摸”。我取消勾选它,它立即显示手指触摸屏幕。

            我正在使用一个自定义绘制例程来检查 isHighlighted 值。您还需要在自定义单元格中覆盖 setHighlighted,如下所示,否则绘制例程永远不会被调用。

            -(void)setHighlighted:(BOOL)highlighted
            {
                [super setHighlighted:highlighted];
                [self setNeedsDisplay];
            }
            

            【讨论】:

            • 感谢有关“延迟内容触摸”的提示!我有同样的快速点击问题。
            • 同池川,感谢有关“延迟内容触摸”的提示。
            猜你喜欢
            • 1970-01-01
            • 2014-02-03
            • 2011-05-01
            • 2011-07-18
            • 2012-12-03
            • 1970-01-01
            • 1970-01-01
            • 2012-12-14
            • 1970-01-01
            相关资源
            最近更新 更多