UIActivityIndi​​catorView不在UICollectionViewCell中旋转

时间:2014-03-18 08:30:54

标签: ios iphone uicollectionview uiactivityindicatorview

我有一个自定义单元格,它加载在我的集合视图的底部。它唯一的工作就是显示一个活动指示器视图 - 当应用程序正在进行新的工作调用时会发生这种情况。

所以我把它添加到单元格中就像这样:

BBLoaderCell *loaderCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"LoaderCell" forIndexPath:indexPath];


UIActivityIndicatorView * activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityIndicator.hidesWhenStopped = YES;
activityIndicator.hidden = NO;
activityIndicator.center = loaderCell.imageView.center;
activityIndicator.tag = 10;

[loaderCell.imageView addSubview:activityIndicator];

    [activityIndicator startAnimating];
    return loaderCell;

这会在我视图的最后一个单元格中显示一个活动指示器 - 但它不会旋转。有什么想法吗?

找到解决方案

根据评论 - 这是一个线程问题。我还建议将代码移动到单元格的自定义nib文件中。

这是重构的代码:

BBLoaderCell *loaderCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"LoaderCell" forIndexPath:indexPath];
    loaderCell.backgroundColor = [UIColor clearColor];

     if (self.loadingMore == NO){
        dispatch_async(dispatch_get_main_queue(), ^{
            activityIndicator.hidden = YES;
            [loaderCell.spinner stopAnimating];
        });
    }
     else if (self.loadingMore == YES){
    dispatch_async(dispatch_get_main_queue(), ^{
        activityIndicator.hidden = NO;
        [loaderCell.spinner startAnimating];
    });
    }

    return loaderCell;

这是我需要的。

谢谢你们!

4 个答案:

答案 0 :(得分:3)

我认为这可能与线程有关(例如主线程上的UI没有准备好为指标设置动画)。您可以尝试以下内容:

[activityIndicator performSelector:@selector(startAnimating:) withObject:nil afterDelay:1];

这只是一个可能的建议,你应该尝试不同的变化,并检查哪一个强制动画正确和及时的动画。另一种变化:

dispatch_async(dispatch_get_main_queue(), ^{
    [activityIndicator startAnimating];
});

答案 1 :(得分:1)

就我而言,我在 tableView 的 customCell 上使用了 activityIndi​​cator,但我遇到了同样的问题,即使在写下 activityIndi​​cator.startAnimating() 之后,加载也没有移动。

经过数小时的尝试,我想出了一个解决方案。

override func prepareForReuse() {
       activityIndicator.startAnimating()
}

当您重用活动指示器正在设置动画的 customCell 时,只需使用 prepareForReuse() 方法显示

答案 2 :(得分:1)

您很可能在很短的时间内多次调用 reloadData。也许已经在下一帧了。默认情况下,活动指示器在停止时隐藏。事情是这样的:

  1. 首先 reloadData 显示微调器
  2. 第二次 reloadData 也会重新加载单元格,并且微调器隐藏自己
  3. 现在微调器已隐藏
  4. 您四处滚动,但单元格被重用了。微调器仍然隐藏

您可以设置activityIndicator.hidesWhenStopped = false。微调器现在应该始终可见。但它没有旋转。

添加这个将恢复旋转。

override func prepareForReuse() {
   activityIndicator.startAnimating()
}

另一个问题可能是颜色。也许微调器具有与背景相同的颜色。尝试像这样设置微调器的颜色:

activityIndicator.color = .red

您可以使用“调试视图层次结构”按钮检查微调器是否存在 Debug View Hierarchie

它将显示当前可见屏幕的线框 Wireframe

答案 3 :(得分:0)

更巧妙的解决方案是使用willDisplay委托方法启动动画:

public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
  (cell as? BBLoaderCell)?.activityIndicatorView.startAnimating()
}

由于在iOS 10或更高版本上,默认情况下启用了预取,因此即使单元格在屏幕上滚动了多次,也可能只有1个cellForItemAt调用。当单元格从屏幕上滚动出来时,似乎stopAnimating()被调用了(isAnimating也变成了false)。因此,在单元格第二次进入屏幕后,在cellForItemAt中使用异步延迟可能会失败。在iOS 11上仍然如此

由于只要单元进入屏幕,就会调用willDisplay,因此我们可以在那里可靠地重新启动动画