在UITableView中实现如下图右边所示的分section圆角的效果:

 

 

 

可以在tableView的willDisplayCell回调中实现,常用的实现方式有两种

  • 根据cell在section中的位置,利用UIBezierPath绘制蒙层,从而实现分区圆角

cell可分为4种:

1. 当前section有且仅有1行,此时该行cell既是第一行的cell,也是最后一行的cell,四个角都要绘制圆角

2. 每个section中第一行的cell,且当前section不止1行,此时cell的左上角和右上角需要绘制圆角

3. 每个section中最后一行的cell,且当前section不止1行,此时cell的左下角和右下角需要绘制圆角

4. 当前cell既不是所在section的第一行,也不是最后一行,则cell的四个角都不需要绘制圆角

实现代码参考:

 

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    
    // Cell 分区圆角
    CGFloat radius = 10;
    if ([tableView numberOfRowsInSection:indexPath.section] == 1) {
        // 当前section有且仅有1行,则四个角都要绘制圆角
        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:radius];
        CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
        maskLayer.frame = cell.bounds;
        maskLayer.path = maskPath.CGPath;
        cell.layer.mask = maskLayer;
    } else {
        // 当前section不止1行
        if (indexPath.row == 0) {
            // 当前cell为第一行
            UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:cell.bounds
                                                       byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight
                                                             cornerRadii:CGSizeMake(radius, radius)];
            CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
            maskLayer.frame = cell.bounds;
            maskLayer.path = maskPath.CGPath;
            cell.layer.mask = maskLayer;
          
        } else if (indexPath.row == [tableView numberOfRowsInSection] - 1) {
            // 当前cell为最后一行
            UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:cell.bounds
                                                       byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
                                                             cornerRadii:CGSizeMake(radius, radius)];
            CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
            maskLayer.frame = cell.bounds;
            maskLayer.path = maskPath.CGPath;
            cell.layer.mask = maskLayer;
        } else {
            // 当前cell为中间行
            cell.layer.mask = nil;
        }
    }
}

 

注意当cell为中间行时需要将cell.layer.mask置为nil,否则由于cell的重用机制,会出现section中间行的cell也被绘制圆角的异常情况。

 

  • 用UIBezierPath绘制蒙层,之后通过设置UITableViewCell的backgroundView和selectedBackgroundView实现分区圆角

cell的分类方式与第一种方法相同

实现代码参考:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
        // Cell 分区圆角
    cell.backgroundColor = [UIColor clearColor];
    CGFloat radius = 10;

    CAShapeLayer *normalLayer = [[CAShapeLayer alloc] init];
    CAShapeLayer *selectLayer = [[CAShapeLayer alloc] init];

    NSInteger rowNumber = [tableView numberOfRowsInSection:indexPath.section];

    UIBezierPath *bezierPath = nil;
    if (rowNumber == 1) {
        bezierPath = [UIBezierPath bezierPathWithRoundedRect:cell.bounds
                                           byRoundingCorners:UIRectCornerAllCorners
                                                 cornerRadii:CGSizeMake(radius, radius)];
    } else {
        if (indexPath.row == 0) {
            bezierPath = [UIBezierPath bezierPathWithRoundedRect:cell.bounds
                                               byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight
                                                     cornerRadii:CGSizeMake(radius, radius)];
        } else if (indexPath.row == rowNumber - 1) {
            bezierPath = [UIBezierPath bezierPathWithRoundedRect:cell.bounds
                                               byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
                                                     cornerRadii:CGSizeMake(radius, radius)];
        } else {
            bezierPath = [UIBezierPath bezierPathWithRect:cell.bounds];
        }
    }

    normalLayer.path = bezierPath.CGPath;
    selectLayer.path = bezierPath.CGPath;

    UIView *normalBgView = [[UIView alloc] initWithFrame:cell.bounds];
    normalLayer.fillColor = [[UIColor whiteColor] CGColor];
    [normalBgView.layer insertSublayer:normalLayer atIndex:0];
    normalBgView.backgroundColor = [UIColor clearColor];
    cell.backgroundView = normalBgView;

    UIView *selectBgView = [[UIView alloc] initWithFrame:cell.bounds];
    selectLayer.fillColor = [[UIColor blackColor] CGColor];
    [selectBgView.layer insertSublayer:selectLayer atIndex:0];
    selectBgView.backgroundColor = [UIColor clearColor];
    cell.selectedBackgroundView = selectBgView;

这种方法的好处在于可以设置cell的fillColor,即选中时的颜色,记得要用UIColor.CGColor,否则颜色无法展示。但是这种实现比第一种方法更加重量级,如果只需要给UITableViewCell绘制分区圆角,推荐第一种方式