【问题标题】:Setting corner radius on a cell kills UICollectionView's performance在单元格上设置角半径会破坏 UICollectionView 的性能
【发布时间】:2012-12-20 20:24:46
【问题描述】:

我有一个UICollectionView,它只有几个单元格(大约 20 个)。这个集合的性能很好。但是,一旦我尝试绕过此视图正在呈现的UICollectionViewCells 的角落,我的性能就会受到重大影响。在我的单元格的 init 方法中,这是我添加的唯一一行:

[self.layer setCornerRadius:15];

由于这是在 init 方法中,并且我正在正确地重用单元格,我不明白为什么这会导致我出现问题。

我尝试使用以下多种组合来调整销售的光栅化和不透明度,但仍然没有效果:

[self.layer setMasksToBounds:YES];
[self.layer setCornerRadius:15];
[self.layer setRasterizationScale:[[UIScreen mainScreen] scale]];
self.layer.shouldRasterize = YES;
self.layer.opaque = YES;

他们是否有一些设置或技巧来提高具有圆角单元格的UICollectionView 的性能?

【问题讨论】:

  • 如果可能的话,使用预渲染图像来获得相同的效果 - 通过这些图层属性完成的角半径和阴影相当昂贵。
  • 单元重用也无济于事;为了实现圆角,iOS 必须重新计算在单元格移动时每帧应该裁剪的内容(如果有任何变化)。不过没有阴影那么糟糕。
  • 我曾想过尝试这样做,但我试图避免它,因为我的单元格中有可变文本。此外,属性 shouldRasterize=YES 是否在渲染之前创建图层的图像?

标签: ios uicollectionview uicollectionviewcell


【解决方案1】:

正如@Till 在 cmets 中指出的那样,预渲染图像应该可以解决您的性能问题。您可以将所有圆角、阴影和任何其他特殊效果放入其中,而不需要 CA 即时渲染它们。

预渲染图像也不会将您锁定在静态内容大小中:查看UIImage resizable image 的内容。 (这仍然比 CA 渲染每一帧要快得多。)

【讨论】:

  • 确实如此。但是,如果您对图像不小心,您仍然可以获得可怕的性能。我们的设计师不小心在 Photoshop 中将整个画布的不透明度设置为 95%,然后将其导出为 PNG。滚动很糟糕,仪器显示整个图像是透明的。因此,如果您发现自己在图像滚动时遇到问题,请仔细检查它们的 alpha 值。
【解决方案2】:

我发现这完全是由于对 dequeuereusablecellwithidentifier 的调用引起的。每次调用时,都需要重新渲染圆角单元格。如果在项目滚动离开屏幕时集合视图没有将它们从视图中删除,那么性能不会受到影响(只要它们在集合中的项目不是太多)。似乎是一把双刃剑 - 两种方式都有其局限性。

【讨论】:

    【解决方案3】:

    有一个 UIView 子类的代码,它为您提供一个带有不透明圆形边框和中间透明孔的视图。 您应该像往常一样创建所需的视图,然后您可以在视图上添加带有孔的视图。可视化是here

    如果您为 UICollectionView 或 UITableView 使用单色背景,则可以为每个单元格添加以下子视图:

    @interface TPRoundedFrameView : UIView
    
    @property (assign, nonatomic) CGFloat cornerRadius;
    @property (strong, nonatomic) UIColor * borderColor;
    
    @end
    
    @implementation TPRoundedFrameView
    
    - (instancetype)init {
        if ((self = [super init])) {
            self.opaque = NO;
            self.backgroundColor = [UIColor clearColor];
        }
        return self;
    }
    
    - (void)drawRect:(CGRect)rect {
        [super drawRect:rect];
    
        UIBezierPath * path = [UIBezierPath bezierPathWithRect:rect];
        UIBezierPath * innerPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:self.cornerRadius];
        [path appendPath:[innerPath bezierPathByReversingPath]];
        [self.borderColor set];
        [path fill];
    }
    
    @end
    

    目标单元类示例:

    - (void)awakeFromNib {
        [super awakeFromNib];
        // creating holed view with rounded corners
        self.myRoundedView.backgroundColor = [UIColor whiteColor];
        TPRoundedFrameView * roundedFrame = [TPRoundedFrameView new];
        roundedFrame.cornerRadius = 5.f;
        roundedFrame.borderColor = [UIColor groupTableViewBackgroundColor];
    
        // add borders to your view with appropriate constraints
        [self.myRoundedView addSubview:roundedFrame];
    
        roundedFrame.translatesAutoresizingMaskIntoConstraints = NO;
        NSDictionary * views = NSDictionaryOfVariableBindings(roundedFrame);
        NSArray * horizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[roundedFrame]-0-|" options:0 metrics:nil views:views];
        NSArray * vertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[roundedFrame]-0-|" options:0 metrics:nil views:views];
        [self.myRoundedView addConstraints:horizontal];
        [self.myRoundedView addConstraints:vertical];
    }
    

    结果: Table 圆形视图作为单元格

    【讨论】:

      【解决方案4】:

      我通过将此半径应用于 contentView 而不是单元格本身来解决我的所有性能边界半径问题。

      self.contentView.layer.borderWidth = 1.0f;
      self.contentView.layer.cornerRadius = 5.0f;
      self.contentView.layer.borderColor = [UIColor colorWithRed:202/255. green:202/255. blue:202/255. alpha:1.0].CGColor;
      

      【讨论】:

        猜你喜欢
        • 2021-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-14
        • 2016-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多