在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绘制分区圆角,推荐第一种方式。