【问题标题】:UICollectionView cells stay highlighted after reloaddataUICollectionView 单元格在重新加载数据后保持突出显示
【发布时间】:2013-05-19 19:27:11
【问题描述】:

我有一个UICollectionView,其单元格内的标签会定期自动更改。当此更新触发时,我在 UICollectionView 上调用 reloadData 并设置单元格以更改 [UICollectionViewCell setHighlighted:]. 上的背景颜色

问题是,如果用户按住某个单元格,则会发生更新,当用户松开该单元格时,该单元格将保持突出显示状态,并且也无法再被选中。

我注意到dequeueReusableCellWithReuseIdentifier:forIndexPath: 在 reloadData 之后对单元格调用 setHighlighted。

我也尝试过reloadSections: 而不是 reloadData,这解决了单元格“卡住”的问题,但在调用单元格时会导致淡出和淡入。

将调用放在performBatchUpdates: 中似乎也不能解决问题。

【问题讨论】:

  • 您是否实现了 didUnhighlightItemAtIndexPath: 来更改单元格背景颜色??
  • 背景颜色设置与否似乎无关紧要,单元格仍然无法选择。
  • 这似乎阻止了reloadSections:stackoverflow.com/a/15068865/667834的淡入/淡出

标签: ios objective-c uicollectionview reloaddata


【解决方案1】:

在单元格的类中尝试调用:

- (void)prepareForReuse {
    [super prepareForReuse];
    [self setHighlighted:NO];
    ... Any other custom stuff that should be cleaned up ...
}

问题在于,您的背景颜色可能与单元格在突出显示时通常会在其自身上做的不同。通常,单元格的超类会撤消 prepareForReuse 中的这些更改,但它不知道您的更改。

【讨论】:

  • 在 prepareForReuse 中清理自定义的东西显然是 UICollectionViewCell 必须做的。但是我看不到您的回答将如何帮助重新突出显示单元格并解决在 reloadData 调用后单元格被“堆叠”的问题。
  • @AlexanderDvornikov:您希望单元格在重新加载后保持由用户选择是否正确?或者我们可以将单元格设置为取消选择状态并且用户必须再次选择它们?
  • 你是对的,我希望与 UITableView 中的行为相同 - 当 tableView 重新加载时,按下的单元格应该保持突出显示。基本上,您可以在 Google Drive 或 eBay 应用程序中发现相同的错误 - 当用户在触发下拉刷新后突出显示单元格时,内容集合视图重新加载并且按下的单元格保持突出显示和堆叠。
【解决方案2】:

我使用以下解决方法:

// Both highlightedData and lastHighlightedData are only needed if you want to prevent user from selecting a cell which data changed during the reload. If not needed, a boolean may be used instead
@property (nonatomic) id highlightedData;
@property (nonatomic) id lastHighlightedData;
@property (nonatomic) BOOL pendingCollectionViewReload;

// Wrap the reloadData call. Enqueue it if there's a highlighted cell:
- (void)reloadCollectionView
{
    if (self.highlightedData) {
        self.pendingCollectionViewReload = YES;
        return;
    }

    [self.collectionView reloadData];
    self.pendingCollectionViewReload = NO;
}

// When a cell is highlighted, save its index, or better the related data:
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    // Save data at indexPath to self.highlightedData
}    

// Then reload the data when the cell is unhighlighted:
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    self.lastHighlightedData = self.highlightedData;
    self.highlightedData = nil;

    if (self.pendingCollectionViewReload) {
        [self reloadCollectionView];
    }
}

// The following can be used from shouldPerformSegueWithIdentifier or didSelectItemAtIndexPath to prevent actions if the data associated with the indexPath changed:
- (BOOL)selectedDataEquals:(id)data
{
    // I used lastHighlightedData in addition to highlightedData because this function may be used after the didUnhighlightItemAtIndexPath was called:
    return (self.highlightedData && self.highlightedData == data) || (!self.highlightedData && self.lastHighlightedData == data);
}

【讨论】:

  • 这个方法对我有用——只是防止集合视图在项目被突出显示时重新加载,并在项目变为未突出显示后重新加载。
【解决方案3】:

我在不需要突出显示的集合视图中遇到了同样的问题,我注意到 didHighlight/didUnhighlight 方法的行为正确,所以我最终在触摸正在进行时阻止了重新加载,使用如下:

BOOL blockColviewUpdate,colviewUpdateQueued;

然后

-(void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    blockColviewUpdate=YES;
}

-(void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
    blockColviewUpdate=NO;
    if(colviewUpdateQueued==YES) [self CollectionViewRefresh];
}

使用自己的函数而不是直接调用 reloadData:

-(void)CollectionViewRefresh
{
    if(blockColviewUpdate==YES) colviewUpdateQueued=YES;
    else
    {
        colviewUpdateQueued=NO;
        [self.colview reloadData];
    }
}

它对我的情况有所帮助,并且没有丢失任何重新加载。

【讨论】:

    【解决方案4】:

    我在最近的一个项目中使用集合视图,以下代码对我来说很好。

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

    在collectionviewcell子类中

    @interface SalesLegendCell : UICollectionViewCell

    下面是代码

        - (id)initWithFrame:(CGRect)frame {    
        self = [super initWithFrame:frame];    
        if (self) {
            // Initialization code
            NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"SalesLegendCell" owner:self options:nil];
    
            if ([arrayOfViews count] < 1) {
                return nil;
            }
    
            if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[SalesLegendCell class]]) {
                return nil;
            }
    
            self = [arrayOfViews objectAtIndex:0];
    
            UIView* backgroundView = [[UIView alloc] initWithFrame:self.bounds];
            backgroundView.backgroundColor = [UIColor colorWithWhite:0.85 alpha:1];
    
            UIView* selectedBGView = [[UIView alloc] initWithFrame:self.bounds];
            selectedBGView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:1];
    
            self.selectedBackgroundView = backgroundView;
            self.backgroundView = selectedBGView;        
        }
        return self;
    }
    

    【讨论】:

      【解决方案5】:

      可能不相关,但这让我很反感:UIViewCollectionCell 在.alwaysTemplate 模式下呈现的UIImage 实例默认突出显示。

      【讨论】:

        猜你喜欢
        • 2014-11-07
        • 2011-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多