最近項目UI需求tableViewCell 帶圓角邊框,自己寫了下像平常那樣去設置圓角邊框行不通網(wǎng)上差了一下自己又改進一下徙歼,廢話不多說先看圖在擼代碼犁河。
圖片效果如下:
實現(xiàn)上面效果暫時想到兩種辦法:
一、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;
// 創(chuàng)建一個shapeLayer
CAShapeLayer *layer = [[CAShapeLayer alloc] init];
CAShapeLayer *backgroundLayer = [[CAShapeLayer alloc] init]; //顯示選中
// 創(chuàng)建一個可變的圖像Path句柄,該路徑用于保存繪圖信息
CGMutablePathRef pathRef = CGPathCreateMutable();
// 獲取cell的size
// 第一個參數(shù),是整個 cell 的 bounds, 第二個參數(shù)是距左右兩端的距離,第三個參數(shù)是距上下兩端的距離
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);
// 終點坐標為右下角坐標點粥脚,把繪圖信息都放到路徑中去,根據(jù)這些路徑就構成了一塊區(qū)域了
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));
}
// 把已經(jīng)繪制好的可變圖像路徑賦值給圖層窃肠,然后圖層根據(jù)這圖像path進行圖像渲染render
layer.path = pathRef;
backgroundLayer.path = pathRef;
// 注意:但凡通過Quartz2D中帶有creat/copy/retain方法創(chuàng)建出來的值都必須要釋放
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作為基類冤留,由它承載邊框的實現(xiàn)碧囊;然后再繼承于BaseBorderCell自定義cell進行內(nèi)容展示;
[參考](http://www.reibang.com/p/8374fdc7b180)
- BaseBorderCell.h文件
//此cell只簡單負責border的配置纤怒,cell中的內(nèi)容可以繼承于此類再進行封裝
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;//邊框內(nèi)部內(nèi)容顏色
@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
###個人喜歡第一種簡單高效副作用小