Seguí adelante y personalicé aún más willDisplayCell para obtener una mejor simulación de los estilos de celda en la aplicación de configuración.
C objetivo
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell respondsToSelector:@selector(tintColor)]) {
if (tableView == self.tableView) {
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);
layer.fillColor = [UIColor colorWithWhite:1.f alpha:0.8f].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-10, 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;
}
}
}
Rápido
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if (cell.respondsToSelector(Selector("tintColor"))){
if (tableView == self.tableView) {
let cornerRadius : CGFloat = 12.0
cell.backgroundColor = UIColor.clearColor()
var layer: CAShapeLayer = CAShapeLayer()
var pathRef:CGMutablePathRef = CGPathCreateMutable()
var bounds: CGRect = CGRectInset(cell.bounds, 25, 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
layer.fillColor = UIColor(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: 0.8).CGColor
if (addLine == true) {
var lineLayer: CALayer = CALayer()
var lineHeight: CGFloat = (1.0 / UIScreen.mainScreen().scale)
lineLayer.frame = CGRectMake(CGRectGetMinX(bounds)+10, bounds.size.height-lineHeight, bounds.size.width-10, 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
}
}
}
Swift 3
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let cornerRadius: CGFloat = 5
cell.backgroundColor = .clear
let layer = CAShapeLayer()
let pathRef = CGMutablePath()
let bounds = cell.bounds.insetBy(dx: 20, 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)
addLine = true
}
layer.path = pathRef
layer.fillColor = UIColor(white: 1, alpha: 0.8).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 = tableView.separatorColor?.cgColor
layer.addSublayer(lineLayer)
}
let testView = UIView(frame: bounds)
testView.layer.insertSublayer(layer, at: 0)
testView.backgroundColor = .clear
cell.backgroundView = testView
}
Rápido 4.2
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if (cell.responds(to: #selector(getter: UIView.tintColor))){
if tableView == self.tableView {
let cornerRadius: CGFloat = 12.0
cell.backgroundColor = .clear
let layer: CAShapeLayer = CAShapeLayer()
let path: CGMutablePath = CGMutablePath()
let bounds: CGRect = cell.bounds
bounds.insetBy(dx: 25.0, dy: 0.0)
var addLine: Bool = false
if indexPath.row == 0 && indexPath.row == ( tableView.numberOfRows(inSection: indexPath.section) - 1) {
path.addRoundedRect(in: bounds, cornerWidth: cornerRadius, cornerHeight: cornerRadius)
} else if indexPath.row == 0 {
path.move(to: CGPoint(x: bounds.minX, y: bounds.maxY))
path.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.minY), tangent2End: CGPoint(x: bounds.midX, y: bounds.minY), radius: cornerRadius)
path.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.minY), tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
} else if indexPath.row == (tableView.numberOfRows(inSection: indexPath.section) - 1) {
path.move(to: CGPoint(x: bounds.minX, y: bounds.minY))
path.addArc(tangent1End: CGPoint(x: bounds.minX, y: bounds.maxY), tangent2End: CGPoint(x: bounds.midX, y: bounds.maxY), radius: cornerRadius)
path.addArc(tangent1End: CGPoint(x: bounds.maxX, y: bounds.maxY), tangent2End: CGPoint(x: bounds.maxX, y: bounds.midY), radius: cornerRadius)
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
} else {
path.addRect(bounds)
addLine = true
}
layer.path = path
layer.fillColor = UIColor.white.withAlphaComponent(0.8).cgColor
if addLine {
let lineLayer: CALayer = CALayer()
let lineHeight: CGFloat = 1.0 / UIScreen.main.scale
lineLayer.frame = CGRect(x: bounds.minX + 10.0, 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 = .clear
cell.backgroundView = testView
}
}
}
[UIBezierPath bezierPathWithRoundedRect:bounds byRoundingCorners:corner cornerRadii:cornerSize];
En iOS 13 y versiones posteriores, Apple finalmente pone a disposición este estilo de tabla, sin tener que rediseñarlo, con el nuevo UITableView.Style.insetGrouped estilo de vista de tabla .
En Xcode 11 y posteriores, esto se puede configurar en la configuración del generador de interfaces para la vista de tabla, seleccionando Inset Grouped para el Estilo:
fuente
Respondiendo a @NarasimhaiahKolli, sobre cómo configuro la vista de fondo de la celda para que la celda completa no se vea resaltada. Espero que esto ayude.
fuente
La respuesta de @jvanmetre es genial y funciona. Sobre la base de eso y como lo sugiere @SergiySalyuk en los comentarios. Actualicé el código para usar UIBezierPath en lugar de hacerlo más simple de entender y un poco más rápido.
Mi versión también corrige el error del separador y agrega una vista de fondo seleccionada que se ajusta a la celda.
Recuerde establecer la vista de la tabla sin separador:
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
C objetivo
fuente
Estaba tratando de lograr el mismo aspecto redondeado de la aplicación Configuración en las celdas de vista de mesa. Mi respuesta también se basa en una respuesta SO sobre cómo configurar cornerRadius solo para la esquina superior izquierda y superior derecha de una UIView. .
fuente
Después de probar algunas de las respuestas aquí, decidí ir por completo e implementar una subclase completa
UITableView
yUITableViewCell
replicar el estilo de vista de tabla agrupada redondeada en iOS 7.https://github.com/TimOliver/TORoundedTableView
Terminó siendo un proceso muy complicado:
layoutSubviews
enUITableView
que la redistribución cada célula y vistas complementarias, de manera que ya no estaban de borde a borde.UITableViewCell
para eliminar las vistas de la línea del cabello del separador superior e inferior (pero dejando las que están dentro de la sección sin tocar).UITableViewCell
vista de fondo personalizada que, opcionalmente, podría tener esquinas redondeadas en la parte superior e inferior para usarla en la primera y última celda de cada sección. Esos elementos debían serCALayer
para evitarUITableView
el comportamiento implícito de cambiar el color de las vistas de fondo cuando un usuario toca la celda.CALayer
instancias que no respondenlayoutSubviews
, tuve que hacer algunos retoques en la animación principal para asegurar que las celdas superior e inferior cambiaran de tamaño a la misma velocidad que las otras celdas cuando el usuario gira el dispositivo.En general, es posible hacerlo, pero dado que requiere un poco de esfuerzo y cuesta una pequeña cantidad de rendimiento (ya que está constantemente luchando contra el código de Apple tratando de retrasar todo), lo mejor sería presentar un radar con Apple solicitándoles exponer oficialmente ese estilo. Hasta entonces, no dudes en utilizar mi biblioteca. :)
fuente
He creado un método llamado
addRoundedCornersWithRadius:(CGFloat)radius ForCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
que creará esquinas redondeadas en la parte superior e inferior de cada sección.La ventaja de utilizar la
maskView
propiedad deUITableViewCell
es que cuando selecciona la celda, las esquinas redondeadas siguen siendo visibles.fuente
Puede que mi respuesta sea demasiado tarde pero para la versión Swift (cualquiera), seguramente será útil y muy fácil de usar.
PD: He usado el siguiente código para Swift 3.0.
fuente
código de trabajo para Swift ... lo que realmente estamos haciendo es si la sección tiene solo una fila, entonces lo hacemos en todos los lados, si la sección tiene varias filas, lo hacemos en la parte superior de la primera fila y en la parte inferior de la última fila ... las propiedades BottomLeft, BottomRight, topLeft, TopRight debe ser de tipo rect corner (sugerencias de xcode cuando está escribiendo ... hay otra esquina de contenido de propiedad con el mismo nombre ... así que verifique eso)
fuente
Me temo que no parece haber una manera fácil de hacer esto. Tendrá que personalizar su UITableViewCell, algo como esto funciona:
Establezca el estilo de su tableView en agrupado.
Establezca el color de fondo de TableView en un color claro.
En su:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)
aclare el fondo de la celda y cree una vista UIV con las esquinas redondeadas deseadas como fondo. Algo como esto:Es posible que deba pulir un poco más, pero esta es la idea principal.
fuente
Quería lograr lo mismo pero con un borde alrededor de cada sección (línea en iOS6). Como no encontré una modificación fácil de las soluciones sugeridas, se me ocurrió la mía propia. Es una modificación de la respuesta que dio @Roberto Ferraz en este tema. Creé una clase personalizada que hereda de UITableViewCell. En él agregué una vista de contenedor con el tamaño apropiado (en mi caso encogido en ambos lados con 15px). Que en la clase hice esto:
Luego, en su fuente de datos, haga esto:
Y listo, tienes esquinas redondeadas Y bordes en tus secciones.
¡Espero que esto ayude!
PD: Realicé algunas ediciones ya que encontré algunos errores en el código original; principalmente no configuré todos los valores en todos los casos, lo que causa algunos efectos muy sorprendentes cuando las celdas se reutilizan :)
fuente
swift 4 En caso de que desee incluir el encabezado de la sección también, intente debajo de uno
declarar cornerLayerWidth como variable global
var cornerLayerWidth: CGFloat = 0.0
y
fuente
En Swift 4.2:
Usar:
Si la celda es la primera de un grupo, establezca
top = True
, si es la última celdabottom = true
, si la celda es la única del grupo, establezca ambos entrue
.Si quieres más o menos redondeado, simplemente cambia las radios de 10 a otro valor.
fuente
Este código establecerá esquinas redondeadas para la vista de tabla completa en lugar de una sola celda.
Y borre el color de fondo de cada celda en cellForRow
fuente
Agregue esto para eliminar la línea superior en la vista de tabla self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
fuente