Как мы можем иметь границу вокруг каждого раздела таблицы? Прикрепленное изображение, чтобы показать, что я ищу. Если вы посмотрите на изображение, у него есть граница вокруг каждого раздела таблицы.
Как мы можем иметь границу вокруг каждого раздела таблицы? Прикрепленное изображение, чтобы показать, что я ищу. Если вы посмотрите на изображение, у него есть граница вокруг каждого раздела таблицы.
В этом выпуске я адаптировал ответ jvanmetre для округления углов tableviews, просто добавьте метод делегата tableView:willDisplayCell:forRowAtIndexPath:
со следующим кодом (простая копия/вставка должен работать), он должен работать и для сгруппированных таблиц. Я прокомментировал, где вы должны установить ширину и цвет границы.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell respondsToSelector:@selector(tintColor)]) {
CGFloat cornerRadius = 5.f;
cell.backgroundColor = UIColor.clearColor;
CAShapeLayer *layer = [[CAShapeLayer alloc] init];
CGMutablePathRef pathRef = CGPathCreateMutable();
CGRect bounds = CGRectInset(cell.bounds, 10, 0);
BOOL addLine = NO;
if (indexPath.row == 0 && indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1) {
CGPathAddRoundedRect(pathRef, nil, bounds, cornerRadius, cornerRadius);
} 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));
addLine = YES;
} 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));
} else {
CGPathAddRect(pathRef, nil, bounds);
addLine = YES;
}
layer.path = pathRef;
CFRelease(pathRef);
//set the border color
layer.strokeColor = [UIColor lightGrayColor].CGColor;
//set the border width
layer.lineWidth = 1;
layer.fillColor = [UIColor colorWithWhite:1.f alpha:1.0f].CGColor;
if (addLine == YES) {
CALayer *lineLayer = [[CALayer alloc] init];
CGFloat lineHeight = (1.f / [UIScreen mainScreen].scale);
lineLayer.frame = CGRectMake(CGRectGetMinX(bounds), bounds.size.height-lineHeight, bounds.size.width, lineHeight);
lineLayer.backgroundColor = tableView.separatorColor.CGColor;
[layer addSublayer:lineLayer];
}
UIView *testView = [[UIView alloc] initWithFrame:bounds];
[testView.layer insertSublayer:layer atIndex:0];
testView.backgroundColor = UIColor.clearColor;
cell.backgroundView = testView;
}
}
Также не забудьте установить для свойства разделителя таблицы значение none в построителе интерфейса (по умолчанию это одна строка), если вы создаете таблицу программно, вы должны установить свойство следующим образом:
yourTableView.separatorStyle = UITableViewCellSeparatorStyleNone
Вот ответ Асада обновлен до скорости 3
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if (cell.responds(to: #selector(getter: UIView.tintColor))) {
let cornerRadius: CGFloat = 5
cell.backgroundColor = UIColor.clear
let layer: CAShapeLayer = CAShapeLayer()
let pathRef: CGMutablePath = CGMutablePath()
let bounds: CGRect = cell.bounds.insetBy(dx: 10, dy: 0)
var addLine: Bool = false
if (indexPath.row == 0 && indexPath.row == tableView.numberOfRows(inSection: indexPath.section)-1) {
pathRef.__addRoundedRect(transform: nil, rect: bounds, cornerWidth: cornerRadius, cornerHeight: cornerRadius)
} else if (indexPath.row == 0) {
pathRef.move(to: CGPoint(x:bounds.minX,y:bounds.maxY))
pathRef.addArc(tangent1End: CGPoint(x:bounds.minX,y:bounds.minY), tangent2End: CGPoint(x:bounds.midX,y:bounds.minY), radius: cornerRadius)
pathRef.addArc(tangent1End: CGPoint(x:bounds.maxX,y:bounds.minY), tangent2End: CGPoint(x:bounds.maxX,y:bounds.midY), radius: cornerRadius)
pathRef.addLine(to: CGPoint(x:bounds.maxX,y:bounds.maxY))
addLine = true;
} else if (indexPath.row == tableView.numberOfRows(inSection: indexPath.section)-1) {
pathRef.move(to: CGPoint(x:bounds.minX,y:bounds.minY))
pathRef.addArc(tangent1End: CGPoint(x:bounds.minX,y:bounds.maxY), tangent2End: CGPoint(x:bounds.midX,y:bounds.maxY), radius: cornerRadius)
pathRef.addArc(tangent1End: CGPoint(x:bounds.maxX,y:bounds.maxY), tangent2End: CGPoint(x:bounds.maxX,y:bounds.midY), radius: cornerRadius)
pathRef.addLine(to: CGPoint(x:bounds.maxX,y:bounds.minY))
} else {
pathRef.addRect(bounds)
addLine = true
}
layer.path = pathRef
//CFRelease(pathRef)
//set the border color
layer.strokeColor = UIColor.lightGray.cgColor;
//set the border width
layer.lineWidth = 1
layer.fillColor = UIColor(white: 1, alpha: 1.0).cgColor
if (addLine == true) {
let lineLayer: CALayer = CALayer()
let lineHeight: CGFloat = (1 / UIScreen.main.scale)
lineLayer.frame = CGRect(x:bounds.minX, y:bounds.size.height-lineHeight, width:bounds.size.width, height:lineHeight)
lineLayer.backgroundColor = tableView.separatorColor!.cgColor
layer.addSublayer(lineLayer)
}
let testView: UIView = UIView(frame:bounds)
testView.layer.insertSublayer(layer, at: 0)
testView.backgroundColor = UIColor.clear
cell.backgroundView = testView
}
}
Вы можете использовать стиль UITableViewStyleGrouped
tableview.
Вот еще один мой подход, который может помочь кому-то. Он рисует границу для каждого раздела с предопределенным цветом и шириной без изменения других свойств ячеек. Это не дает вам округленный раздел (возможно, его можно соответствующим образом изменить), но он дает хорошую степень контроля линий, которые нужно рисовать. Подход также относится к вращению устройства.
typedef enum CellBorderMask{
CellBorderMaskLeft = 1 << 0,
CellBorderMaskRigth = 1 << 1,
CellBorderMaskTop = 1 << 2,
CellBorderMaskBottom = 1 << 3
}CellBorderMask;
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
CellBorderMask mask;
if (indexPath.row == 0){
mask |= CellBorderMaskTop;
}
if(indexPath.row == [tableView numberOfRowsInSection:indexPath.section] - 1) {
mask |= CellBorderMaskBottom;
}
mask |= CellBorderMaskRigth | CellBorderMaskLeft;
[self addBorder:mask forView:cell.contentView];
}
-(void)addBorder:(CellBorderMask)mask forView:(UIView *)view{
float onePixel = (1.f / [UIScreen mainScreen].scale);
float lineWidth = 1 * onePixel;
CGColorRef cgBorderColor = [UIColor redColor].CGColor;
CALayer *topBorder = [CALayer layer];
CALayer *bottomBorder = [CALayer layer];
CALayer *leftBorder = [CALayer layer];
CALayer *rightBorder = [CALayer layer];
//tag layers so it possible to find and remove them later
topBorder.name = @"Border";
bottomBorder.name = @"Border";
leftBorder.name = @"Border";
rightBorder.name = @"Border";
//remove previously set border layers so they doesn't produce unwanted effect on orientation change
[self cleanUpOldBorderLayers:view];
topBorder.frame = CGRectMake(0.0f, 0.0f, view.bounds.size.width, lineWidth);
topBorder.backgroundColor = cgBorderColor;
bottomBorder.frame = CGRectMake(0.0f, view.bounds.size.height - lineWidth, view.bounds.size.width, lineWidth);
bottomBorder.backgroundColor = cgBorderColor;
leftBorder.frame = CGRectMake(0.0f, 0.0f, lineWidth, view.bounds.size.height);
leftBorder.backgroundColor = cgBorderColor;
rightBorder.frame = CGRectMake(view.bounds.size.width - lineWidth, 0.0f, lineWidth, view.bounds.size.height);
rightBorder.backgroundColor = cgBorderColor;
if(mask & CellBorderMaskTop){
[view.layer addSublayer:topBorder];
}
if(mask & CellBorderMaskBottom){
[view.layer addSublayer:bottomBorder];
}
if(mask & CellBorderMaskLeft){
[view.layer addSublayer:leftBorder];
}
if(mask & CellBorderMaskRigth){
[view.layer addSublayer:rightBorder];
}
}
-(void)cleanUpOldBorderLayers:(UIView *)view{
NSMutableArray *layerArray = [NSMutableArray new];
for (CALayer *layer in view.layer.sublayers) {
if([@"Border" isEqualToString:layer.name]){
[layerArray addObject:layer];
}
}
for (CALayer *layer in layerArray) {
[layer removeFromSuperlayer];
}
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
//need to trigger tableView:willDisplayCell: method on orientation change.
//Suggest a better method for this if there is one
[self.tableView reloadData];
}
Я использую метод tableView reloadData
для перерисовки ячеек, которые, я считаю, не лучший подход. Проконсультируйтесь с альтернативным методом в комментариях, и я обновлю код.
Чтобы добавить границу в верхний/нижний колонтитул, просто создайте собственное представление в методах делегатов viewForHeaderInSection/viewForFooterInSection и передайте представление методу addBorder:forView
выше, прежде чем возвращать его из вашего делегата.
Вот быстрая версия принятого ответа.
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if (cell.respondsToSelector("tintColor")) {
var cornerRadius: CGFloat = 5;
cell.backgroundColor = UIColor.clearColor()
var layer: CAShapeLayer = CAShapeLayer()
var pathRef: CGMutablePathRef = CGPathCreateMutable()
var bounds: CGRect = CGRectInset(cell.bounds, 10, 0)
var addLine: Bool = false
if (indexPath.row == 0 && indexPath.row == tableView.numberOfRowsInSection(indexPath.section)-1) {
CGPathAddRoundedRect(pathRef, nil, bounds, cornerRadius, cornerRadius);
} 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));
addLine = true;
} 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));
} else {
CGPathAddRect(pathRef, nil, bounds);
addLine = true;
}
layer.path = pathRef;
//CFRelease(pathRef);
//set the border color
layer.strokeColor = UIColor.lightGrayColor().CGColor;
//set the border width
layer.lineWidth = 1;
layer.fillColor = UIColor(white: 1, alpha: 1.0).CGColor;
if (addLine == true) {
var lineLayer: CALayer = CALayer();
var lineHeight: CGFloat = (1 / UIScreen.mainScreen().scale);
lineLayer.frame = CGRectMake(CGRectGetMinX(bounds), bounds.size.height-lineHeight, bounds.size.width, lineHeight);
lineLayer.backgroundColor = tableView.separatorColor!.CGColor;
layer.addSublayer(lineLayer);
}
var testView: UIView = UIView(frame:bounds)
testView.layer.insertSublayer(layer, atIndex: 0)
testView.backgroundColor = UIColor.clearColor()
cell.backgroundView = testView
}
}
Вот версия ответа Swift3:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let cornerRadius: CGFloat = 0.0
cell.backgroundColor = UIColor.clear
let layer: CAShapeLayer = CAShapeLayer()
let pathRef: CGMutablePath = CGMutablePath()
let bounds: CGRect = cell.bounds.insetBy(dx: 10, dy: 0)
var addLine: Bool = false
if indexPath.row == 0 && indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
pathRef.__addRoundedRect(transform: nil, rect: bounds, cornerWidth: cornerRadius, cornerHeight: cornerRadius)
} else if indexPath.row == 0 {
pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.maxY))
pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.minY), tangent2End: CGPoint(x: bounds.midX, y: bounds.minY), radius: cornerRadius)
pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.minY), tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
addLine = true
} else if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
pathRef.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
pathRef.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.maxY), tangent2End: CGPoint(x: bounds.midX, y: bounds.maxY), radius: cornerRadius)
pathRef.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.maxY), tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
pathRef.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
} else {
pathRef.addRect(bounds)
addLine = true
}
layer.path = pathRef
layer.strokeColor = UIColor.black.cgColor
layer.lineWidth = 0.5
layer.fillColor = UIColor(white: 1, alpha: 1.0).cgColor
if addLine == true {
let lineLayer: CALayer = CALayer()
let lineHeight: CGFloat = (1 / UIScreen.main.scale)
lineLayer.frame = CGRect(x: bounds.minX, y: bounds.size.height - lineHeight, width: bounds.size.width, height: lineHeight)
lineLayer.backgroundColor = tableView.separatorColor!.cgColor
layer.addSublayer(lineLayer)
}
let backgroundView: UIView = UIView(frame: bounds)
backgroundView.layer.insertSublayer(layer, at: 0)
backgroundView.backgroundColor = UIColor.clear
cell.backgroundView = backgroundView
}
Я модифицировал выше размещенный код, теперь этот код создает границу для раздела. Протестировано в swift4.2
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let cornerRadius: CGFloat = 24
cell.backgroundColor = .clear
let layer = CAShapeLayer()
let pathRef = CGMutablePath()
let bounds = cell.bounds.insetBy(dx: 10, dy: 0)
var addLine = false
if indexPath.row == 0 && indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
pathRef.__addRoundedRect(transform: nil, rect: bounds, cornerWidth: cornerRadius, cornerHeight: cornerRadius)
} else if indexPath.row == 0 {
pathRef.move(to: .init(x: bounds.minX, y: bounds.maxY))
pathRef.addArc(tangent1End: .init(x: bounds.minX, y: bounds.minY), tangent2End: .init(x: bounds.midX, y: bounds.minY), radius: cornerRadius)
pathRef.addArc(tangent1End: .init(x: bounds.maxX, y: bounds.minY), tangent2End: .init(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
pathRef.addLine(to: .init(x: bounds.maxX, y: bounds.maxY))
addLine = true
} else if indexPath.row == tableView.numberOfRows(inSection: indexPath.section) - 1 {
pathRef.move(to: .init(x: bounds.minX, y: bounds.minY))
pathRef.addArc(tangent1End: .init(x: bounds.minX, y: bounds.maxY), tangent2End: .init(x: bounds.midX, y: bounds.maxY), radius: cornerRadius)
pathRef.addArc(tangent1End: .init(x: bounds.maxX, y: bounds.maxY), tangent2End: .init(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
pathRef.addLine(to: .init(x: bounds.maxX, y: bounds.minY))
} else {
//pathRef.addRect(bounds)
let pathInnerRef = CGMutablePath()
pathInnerRef.move(to: .init(x: bounds.minX, y: bounds.minY))
pathInnerRef.addLine(to: .init(x: bounds.minX, y: bounds.maxY))
pathInnerRef.move(to: .init(x: bounds.maxX, y: bounds.minY))
pathInnerRef.addLine(to: .init(x: bounds.maxX, y: bounds.maxY))
pathRef.addPath(pathInnerRef)
addLine = true
}
layer.path = pathRef
layer.fillColor = UIColor.clear.cgColor
layer.strokeColor = UIColor.black.cgColor
if (addLine == true) {
let lineLayer = CALayer()
let lineHeight = 1.0 / UIScreen.main.scale
lineLayer.frame = CGRect(x: bounds.minX + 10, y: bounds.size.height - lineHeight, width: bounds.size.width - 10, height: lineHeight)
lineLayer.backgroundColor = UIColor.clear.cgColor//tableView.separatorColor?.cgColor
lineLayer.addBorder(edge: .left, color: UIColor.black, thickness: 2.0)
lineLayer.addBorder(edge: .right, color: UIColor.black, thickness: 2.0)
layer.addSublayer(lineLayer)
}
let testView = UIView(frame: bounds)
testView.layer.insertSublayer(layer, at: 0)
testView.backgroundColor = .clear
cell.backgroundView = testView
}