tableView setion cell加边框圆角
最近项目UI需求tableViewCell 带圆角边框,自己写了下像平常那样去设置圆角边框行不通网上差了一下自己又改进一下,废话不多说先看图在撸代码。
图片效果如下:
51499150024_.pic副本.jpg
实现上面效果暂时想到两种办法:
一、cell重绘给section,绘制边框。可以构建基类或者写在category里面,方便使用代码如下:
可直接复制代码到项目中
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// 这里要判断分组列表中的第一行,每组section的第一行,每组section的中间行
// CGPathAddRoundedRect(pathRef, nil, bounds, cornerRadius, cornerRadius);
if (indexPath.section == 2) {
// 圆角弧度半径
CGFloat cornerRadius = 3.f;
// 设置cell的背景色为透明,如果不设置这个的话,则原来的背景色不会被覆盖
cell.backgroundColor = UIColor.clearColor;
// 创建一个shapeLayer
CAShapeLayer *layer = [[CAShapeLayer alloc] init];
CAShapeLayer *backgroundLayer = [[CAShapeLayer alloc] init]; //显示选中
// 创建一个可变的图像Path句柄,该路径用于保存绘图信息
CGMutablePathRef pathRef = CGPathCreateMutable();
// 获取cell的size
// 第一个参数,是整个 cell 的 bounds, 第二个参数是距左右两端的距离,第三个参数是距上下两端的距离
CGRect bounds = CGRectInset(cell.bounds, 10, 0);
// CGRectGetMinY:返回对象顶点坐标
// CGRectGetMaxY:返回对象底点坐标
// CGRectGetMinX:返回对象左边缘坐标
// CGRectGetMaxX:返回对象右边缘坐标
// CGRectGetMidX: 返回对象中心点的X坐标
// CGRectGetMidY: 返回对象中心点的Y坐标
if (indexPath.row == 0 && indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1) {
CGPathAddRoundedRect(pathRef, nil, bounds, cornerRadius, cornerRadius);
}else if (indexPath.row == 0) {
// 初始起点为cell的左下角坐标
CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
// 起始坐标为左下角,设为p,(CGRectGetMinX(bounds), CGRectGetMinY(bounds))为左上角的点,设为p1(x1,y1),(CGRectGetMidX(bounds), CGRectGetMinY(bounds))为顶部中点的点,设为p2(x2,y2)。然后连接p1和p2为一条直线l1,连接初始点p到p1成一条直线l,则在两条直线相交处绘制弧度为r的圆角。
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));
// CGPathCloseSubpath(pathRef);
} else if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1) {
//
// 初始起点为cell的左上角坐标
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));
// CGPathCloseSubpath(pathRef);
} else {
// 添加cell的rectangle信息到path中(不包括圆角)
// CGPathAddRect(pathRef, nil, bounds);
//假如只要边框
CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
CGPathAddLineToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
CGPathMoveToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds));
}
// 把已经绘制好的可变图像路径赋值给图层,然后图层根据这图像path进行图像渲染render
layer.path = pathRef;
backgroundLayer.path = pathRef;
// 注意:但凡通过Quartz2D中带有creat/copy/retain方法创建出来的值都必须要释放
CFRelease(pathRef);
// 按照shape layer的path填充颜色,类似于渲染render
layer.lineWidth = 0.5f;//线的宽度
layer.strokeColor = [UIColor colorWithHex:@"#cccccc"].CGColor;//线的颜色
layer.fillColor = [UIColor whiteColor].CGColor;//cellcell背景色
// view大小与cell一致
UIView *roundView = [[UIView alloc] initWithFrame:bounds];
// 添加自定义圆角后的图层到roundView中
[roundView.layer insertSublayer:layer atIndex:0];
roundView.backgroundColor = UIColor.clearColor;
// cell的背景view
cell.backgroundView = roundView;
cell.backgroundColor = [UIColor whiteColor];
}
}```
***
<p>
####二、自定义一个BaseCell作为基类,由它承载边框的实现;然后再继承于BaseBorderCell自定义cell进行内容展示;
[参考](http://www.jianshu.com/p/8374fdc7b180)
- BaseBorderCell.h文件
//此cell只简单负责border的配置,cell中的内容可以继承于此类再进行封装
typedef NS_ENUM(NSUInteger, BaseCellBorderStyle) {
BaseCellBorderStyleNoRound = 0,
BaseCellBorderStyleTopRound,
BaseCellBorderStyleBottomRound,
BaseCellBorderStyleAllRound,
};
@interface BaseBorderCell : UITableViewCell
@property (nonatomic, assign) BaseCellBorderStyle borderStyle;//边框类型
@property (nonatomic, strong) UIColor *contentBorderColor;//边框颜色
@property (nonatomic, strong) UIColor *contentBackgroundColor;//边框内部内容颜色
@property (nonatomic, assign) CGFloat contentBorderWidth;//边框的宽度,这个宽度的一半会延伸到外部,如果对宽度比较敏感的要注意下
@property (nonatomic, assign) CGFloat contentMargin;//左右距离父视图的边距
@property (nonatomic, assign) CGSize contentCornerRadius;//边框的圆角
- (instancetype)cellWithTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath;
//如果不想用上面的方法初始化cell,就用下面的方法设置borderStyle
- (void)setBorderStyleWithTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath;
@end
- BaseBorderCell.m文件
import "BaseBorderCell.h"
define Width self.contentView.frame.size.width
define Height self.contentView.frame.size.height
@implementation BaseBorderCell
//
- (instancetype)cellWithTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath
{
BaseBorderCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {
cell = [[BaseBorderCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}
//一定要这里设置style,而不能在上面的判断里面,因为cell重用的时候,只要有不同的地方都应该重新设置,否则拿到cell的style就是上一个的样式而自己却没有进行修改
if (indexPath.row == 0 && indexPath.row == [tableView numberOfRowsInSection:indexPath.section] - 1) {
cell.borderStyle = BaseCellBorderStyleAllRound;
}else if (indexPath.row == 0) {
cell.borderStyle = BaseCellBorderStyleTopRound;
}else if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section] - 1) {
cell.borderStyle = BaseCellBorderStyleBottomRound;
}else {
cell.borderStyle = BaseCellBorderStyleNoRound;
}
return cell;
}
-
(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//配置默认值
self.contentBorderColor = [UIColor lightGrayColor];
self.contentBackgroundColor = [UIColor whiteColor];
self.contentBorderWidth = 2.0;
self.contentMargin = 10.0;
self.contentCornerRadius = CGSizeMake(5, 5);
}
return self;
} -
(void)setBorderStyleWithTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0 && indexPath.row == [tableView numberOfRowsInSection:indexPath.section] - 1) {
self.borderStyle = BaseCellBorderStyleAllRound;
}else if (indexPath.row == 0) {
self.borderStyle = BaseCellBorderStyleTopRound;
}else if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section] - 1) {
self.borderStyle = BaseCellBorderStyleBottomRound;
}else {
self.borderStyle = BaseCellBorderStyleNoRound;
}
} -
(void)layoutSubviews
{
[super layoutSubviews];
//在这里设置才能获取到真正显示时候的宽度,而不是原始的
[self setupBorder];
} -
(void)setupBorder
{
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.backgroundColor = [UIColor clearColor];CAShapeLayer *layer = [CAShapeLayer layer];
layer.lineWidth = self.contentBorderWidth;
layer.strokeColor = self.contentBorderColor.CGColor;
layer.fillColor = self.contentBackgroundColor.CGColor;UIView *view = [[UIView alloc] initWithFrame:self.contentView.bounds];
[view.layer insertSublayer:layer atIndex:0];
view.backgroundColor = [UIColor clearColor];
//用自定义的view代替cell的backgroundView
self.backgroundView = view;CGRect rect = CGRectMake(self.contentMargin, 0, Width - 2*self.contentMargin, Height);
switch (self.borderStyle) {
case BaseCellBorderStyleNoRound:
{
UIBezierPath *path = [UIBezierPath bezierPathWithRect:rect];
layer.path = path.CGPath;
}
break;
case BaseCellBorderStyleTopRound:
{
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii:self.contentCornerRadius];
layer.path = path.CGPath;
}
break;
case BaseCellBorderStyleBottomRound:
{
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:self.contentCornerRadius];
layer.path = path.CGPath;
}
break;
case BaseCellBorderStyleAllRound:
{
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:self.contentCornerRadius];
layer.path = path.CGPath;
}
break;
default:
break;
}
}
@end
###个人喜欢第一种简单高效副作用小