欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

tableView圆角封装

程序员文章站 2024-03-23 08:58:16
...

很多界面会使用tableView,系统也提供了UITableViewController,基于它做一下简答的封装,实现tableView的圆角设置。

封装

  • MMTableViewController.h
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface MMTableViewController : UITableViewController

// Set the rounded corners for section, if > 0 the section corner is round.
@property (nonatomic, assign) CGFloat sectionCornerRadius;

@end

NS_ASSUME_NONNULL_END

这里通过属性sectionCornerRadius来设置tableView的圆角。

  • MMTableViewController.m
#import "MMTableViewController.h"

@interface MMTableViewController ()

@end

@implementation MMTableViewController

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Uncomment the following line to preserve selection between presentations.
    // 默认是YES,在viewWillAppear:的时候会清空当前的cell,这里禁止此操作。
    self.clearsSelectionOnViewWillAppear = NO;
    
    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

- (void)setSectionCornerRadius:(CGFloat)sectionCornerRadius
{
    _sectionCornerRadius = sectionCornerRadius;
    
    // 去除tableView自带的线条,否则会和我们绘制的线条重合
    if (_sectionCornerRadius > 0) {
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    }
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 0;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 0;
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 当 sectionCornerRadius > 0 时,设置圆角
    if (self.sectionCornerRadius > 0)
    {
        // 设置cell的背景色透明,否则边角上会显示出来。
        cell.backgroundColor = UIColor.clearColor;

        // 圆角大小
        CGFloat cornerRadius = self.sectionCornerRadius;
        
        CAShapeLayer *layer = [[CAShapeLayer alloc] init]; 
        CAShapeLayer *borderLayer = [[CAShapeLayer alloc] init]; 
        CAShapeLayer *backgroundLayer = [[CAShapeLayer alloc] init];
        
        CGMutablePathRef pathRef = CGPathCreateMutable();
        CGMutablePathRef borderPathRef = CGPathCreateMutable(); 
        
        CGRect bounds = CGRectInset(cell.bounds, 0, 0);
        
        // 是否需要画线,默认为NO
        BOOL addLine = NO;

        // 绘制每个section的第一个和最后一个row
        if (indexPath.row == 0 && indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1)
        {
            CGPathAddRoundedRect(pathRef, nil, bounds, cornerRadius, cornerRadius);
            CGPathAddRoundedRect(borderPathRef, nil, bounds, cornerRadius, cornerRadius);
        }
        // 绘制每个section的第一个cell
        else if (indexPath.row == 0)
        {
            CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds), CGRectGetMidX(bounds), CGRectGetMinY(bounds), cornerRadius);
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
            CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds));
            
            CGPathMoveToPoint(borderPathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
            CGPathAddArcToPoint(borderPathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds), CGRectGetMidX(bounds), CGRectGetMinY(bounds), cornerRadius);
            CGPathAddArcToPoint(borderPathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
            CGPathAddLineToPoint(borderPathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds));
            
            addLine = YES;
        }
        // 绘制每个section的最后个cell
        else if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1)
        {
            CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds), CGRectGetMidX(bounds), CGRectGetMaxY(bounds), cornerRadius);
            CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
            CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
            
            CGPathMoveToPoint(borderPathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
            CGPathAddArcToPoint(borderPathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds), CGRectGetMidX(bounds), CGRectGetMaxY(bounds), cornerRadius);
            CGPathAddArcToPoint(borderPathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
                CGPathAddLineToPoint(borderPathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
        }
        // 绘制每个section中间的cell
        else
        {
            CGPathAddRect(pathRef, nil, bounds);
            
            CGPathMoveToPoint(borderPathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
            CGPathAddLineToPoint(borderPathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
            
            CGPathMoveToPoint(borderPathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
            CGPathAddLineToPoint(borderPathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds));
            
            addLine = YES;
        }
        
        layer.path = pathRef;
        backgroundLayer.path = pathRef;
        CFRelease(pathRef);
        layer.fillColor = [UIColor colorWithWhite:1.f alpha:0.8f].CGColor; //填充颜色

        borderLayer.path = borderPathRef;
        CFRelease(borderPathRef);
        borderLayer.fillColor = [UIColor clearColor].CGColor;   //
        borderLayer.lineWidth = 1/[[UIScreen mainScreen] scale];
        borderLayer.strokeColor = tableView.separatorColor.CGColor;       //绘制边缘

        if (addLine == YES) {
            CALayer *lineLayer = [[CALayer alloc] init];
            CGFloat lineHeight = (1.f / [UIScreen mainScreen].scale);
            lineLayer.frame = CGRectMake(CGRectGetMinX(bounds)+10, bounds.size.height-lineHeight, bounds.size.width-20, lineHeight);
            lineLayer.backgroundColor = tableView.separatorColor.CGColor; //绘制中间间隔线
            [layer addSublayer:lineLayer];
        }
        UIView *testView = [[UIView alloc] initWithFrame:bounds];
        [testView.layer insertSublayer:layer atIndex:0];
        [testView.layer insertSublayer:borderLayer above:layer];
        testView.backgroundColor = UIColor.clearColor;
        cell.backgroundView = testView;
                  
        //以上方法存在缺陷当点击cell时还是出现cell方形效果,因此还需要添加以下方法
        UIView *selectedBackgroundView = [[UIView alloc] initWithFrame:bounds];
        backgroundLayer.fillColor = tableView.separatorColor.CGColor;
        [selectedBackgroundView.layer insertSublayer:backgroundLayer atIndex:0];
        selectedBackgroundView.backgroundColor = UIColor.clearColor;
        cell.selectedBackgroundView = selectedBackgroundView;
    }
}
@end

以上方法是借鉴了网上别人的实现方式,都大差不离。

cell向内缩进

一般的我们设置tableView圆角,会设置cell向内缩进,在自定义的cell里面添加如下设置:

// 设置cell向内缩进
- (void)setFrame:(CGRect)frame
{
    NSInteger insert = 45;
    frame.origin.x += insert;
    frame.size.width -= 2 * insert;
    
    [super setFrame:frame];
}

效果

圆角+缩进tableView圆角封装

直角+缩进:

tableView圆角封装
默认

tableView圆角封装