ios - tutorial - UITableView configurado en celdas estáticas. ¿Es posible ocultar algunas de las celdas programáticamente?
uitableviewcontroller swift 4 (20)
UITableView
configurado en celdas estáticas.
¿Es posible ocultar algunas de las celdas programáticamente?
Método simple iOS 11 y IB / Storyboard Compatible
Para iOS 11, descubrí que una versión modificada de la respuesta de Mohamed Saleh funcionaba mejor, con algunas mejoras basadas en la documentación de Apple. Se anima muy bien, evita los piratas informáticos feos o los valores codificados, y utiliza alturas de fila ya configuradas en el Interface Builder .
El concepto básico es establecer la altura de la fila en 0 para las filas ocultas. Luego use tableView.performBatchUpdates
para activar una animación que funcione de manera consistente.
Establecer las alturas de las celdas
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath == indexPathOfHiddenCell {
if cellIsHidden {
return 0
}
}
// Calling super will use the height set in your storyboard, avoiding hardcoded values
return super.tableView(tableView, heightForRowAt: indexPath)
}
Deberá asegurarse de que cellIsHidden
e indexPathOfHiddenCell
estén configurados adecuadamente para su caso de uso. Para mi código, son propiedades en mi controlador de vista de tabla.
Alternar la celda
En cualquier método que controle la visibilidad (probablemente una acción de botón o didSelectRow
), alternar el estado cellIsHidden, dentro de un bloque performBatchUpdates
:
tableView.performBatchUpdates({
// Use self to capture for block
self.cellIsHidden = !self.cellIsHidden
}, completion: nil)
Apple recomienda performBatchUpdates
durante beginUpdates
/ endUpdates
siempre que sea posible.
- En el diseñador, cree una salida para la (s) celda (s) que desea ocultar. Por ejemplo, desea ocultar ''cellOne'', por lo que en viewDidLoad () haga esto
cellOneOutlet.hidden = true
ahora anule el siguiente método, compruebe qué estado de celda está oculto y devuelva la altura 0 para esa (s) celda (s). Esta es una de las muchas formas en que puede ocultar cualquier celda en tableView estático en swift.
override func tableView(tableView: UITableView, heightForRowAtIndexPathindexPath: NSIndexPath) -> CGFloat
{
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
if tableViewCell.hidden == true
{
return 0
}
else{
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
Además de la solución @Saleh Masum:
Si obtiene errores de diseño automático , puede eliminar las restricciones de tableViewCell.contentView
Swift 3:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let tableViewCell = super.tableView(tableView, cellForRowAt: indexPath)
if tableViewCell.isHidden == true
{
tableViewCell.contentView.removeConstraints(tableViewCell.contentView.constraints)
return 0
}
else{
return super.tableView(tableView, heightForRowAt: indexPath)
}
}
Esta solución depende del flujo de tu aplicación . Si desea mostrar / ocultar la celda en la misma instancia de controlador de vista, esta puede no ser la mejor opción, ya que elimina las restricciones .
En> Swift 2.2, he combinado algunas respuestas aquí.
Haga una salida desde el guión gráfico para vincularlo a su staticCell.
@IBOutlet weak var updateStaticCell: UITableViewCell!
override func viewDidLoad() {
...
updateStaticCell.hidden = true
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
return 0
} else {
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
Quiero ocultar mi primera celda, así que establezco la altura en 0 como se describe arriba.
Encontré una solución para ocultar células animadas en la tabla estática.
// Class for wrapping Objective-C block
typedef BOOL (^HidableCellVisibilityFunctor)();
@interface BlockExecutor : NSObject
@property (strong,nonatomic) HidableCellVisibilityFunctor block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block;
@end
@implementation BlockExecutor
@synthesize block = _block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block
{
BlockExecutor * executor = [[BlockExecutor alloc] init];
executor.block = block;
return executor;
}
@end
Solo se necesita un diccionario adicional:
@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end
Y mire la implementación de MyTableViewController. Necesitamos dos métodos para convertir indexPath entre índices visibles e invisibles ...
- (NSIndexPath*)recoverIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row <= indexPath.row + rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row+rowDelta inSection:indexPath.section];
}
- (NSIndexPath*)mapToNewIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row < indexPath.row - rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row-rowDelta inSection:indexPath.section];
}
One IBAction en el cambio de valor de UISwitch:
- (IBAction)birthdaySwitchChanged:(id)sender
{
NSIndexPath * indexPath = [self mapToNewIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
if (self.birthdaySwitch.on)
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
else
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
Algunos métodos UITableViewDataSource y UITableViewDelegate:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int numberOfRows = [super tableView:tableView numberOfRowsInSection:section];
for (NSIndexPath * indexPath in [self.hidableCellsDict allKeys])
if (indexPath.section == section)
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:indexPath];
numberOfRows -= (executor.block()?0:1);
}
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// initializing dictionary
self.hidableCellsDict = [NSMutableDictionary dictionary];
[self.hidableCellsDict setObject:[BlockExecutor executorWithBlock:^(){return self.birthdaySwitch.on;}] forKey:[NSIndexPath indexPathForRow:1 inSection:1]];
}
- (void)viewDidUnload
{
[self setBirthdaySwitch:nil];
[super viewDidUnload];
}
@end
Esta es una nueva forma de hacerlo mediante https://github.com/k06a/ABStaticTableViewController
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
La mejor manera es la descrita en el siguiente blog http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/
Diseñe su vista de tabla estática como es normal en el constructor de interfaz: complete con todas las celdas potencialmente ocultas. Pero hay una cosa que debes hacer por cada celda potencial que quieras ocultar: revisa la propiedad "Clip subviews" de la celda; de lo contrario, el contenido de la celda no desaparecerá cuando trates de ocultarlo (reduciendo su altura). - más tarde).
SO - usted tiene un interruptor en una celda y se supone que el interruptor se oculta y muestra algunas celdas estáticas. Conéctelo a un IBAction y haga esto:
[self.tableView beginUpdates]; [self.tableView endUpdates];
Eso te da buenas animaciones para que las células aparezcan y desaparezcan. Ahora implemente el siguiente método delegado de vista de tabla:
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 1 && indexPath.row == 1) { // This is the cell to hide - change as you need // Show or hide cell if (self.mySwitch.on) { return 44; // Show the cell - adjust the height as you need } else { return 0; // Hide the cell } } return 44; }
Y eso es. Da la vuelta al interruptor y la celda se esconde y reaparece con una animación agradable y suave.
La solución de k06a ( https://github.com/k06a/ABStaticTableViewController ) es mejor porque oculta toda la sección, incluidos los encabezados y pies de página de las celdas, donde esta solución ( https://github.com/peterpaulis/StaticDataTableViewController ) oculta todo, excepto el pie de página.
EDITAR
Acabo de encontrar la solución si desea ocultar el pie de página en StaticDataTableViewController
. Esto es lo que necesita copiar en el archivo StaticTableViewController.m:
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
return nil;
} else {
return [super tableView:tableView titleForFooterInSection:section];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
CGFloat height = [super tableView:tableView heightForFooterInSection:section];
if (self.originalTable == nil) {
return height;
}
if (!self.hideSectionsWithHiddenRows) {
return height;
}
OriginalSection * os = self.originalTable.sections[section];
if ([os numberOfVissibleRows] == 0) {
//return 0;
return CGFLOAT_MIN;
} else {
return height;
}
//return 0;
return CGFLOAT_MIN;
}
Las respuestas anteriores que ocultan / muestran celdas, cambian rowHeight o se confunden con las restricciones de diseño automático no funcionaron para mí debido a problemas de diseño automático. El código se hizo intolerable.
Para una tabla estática simple, lo que funcionó mejor para mí fue:
- Crear una salida para cada celda en la tabla estática
- Crea una matriz solo con las salidas de celdas para mostrar
- Anular cellForRowAtIndexPath para devolver la celda de la matriz
- Anula numberOfRowsInSection para devolver el conteo de la matriz
- Implemente un método para determinar qué celdas deben estar en esa matriz, y llame a ese método cuando sea necesario, y luego vuelva a cargar los datos.
Aquí hay un ejemplo de mi controlador de vista de tabla:
@IBOutlet weak var titleCell: UITableViewCell!
@IBOutlet weak var nagCell: UITableViewCell!
@IBOutlet weak var categoryCell: UITableViewCell!
var cellsToShow: [UITableViewCell] = []
override func viewDidLoad() {
super.viewDidLoad()
determinCellsToShow()
}
func determinCellsToShow() {
if detail!.duration.type != nil {
cellsToShow = [titleCell, nagCell, categoryCell]
}
else {
cellsToShow = [titleCell, categoryCell]
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return cellsToShow[indexPath.row]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsToShow.count
}
Mi solución va en una dirección similar a la de Gareth, aunque hago algunas cosas de manera diferente.
Aquí va:
1. Ocultar las celdas
No hay forma de ocultar directamente las celdas. UITableViewController
es la fuente de datos que proporciona las celdas estáticas, y actualmente no hay forma de decirle "no proporcione la celda x". Por lo tanto, debemos proporcionar nuestra propia fuente de datos, que delega en UITableViewController
para obtener las celdas estáticas.
Lo más fácil es subclasificar UITableViewController
, y anular todos los métodos que necesitan comportarse de manera diferente al ocultar celdas .
En el caso más simple (tabla de sección única, todas las celdas tienen la misma altura), esto sería así:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [super tableView:tableView numberOfRowsInSection:section] - numberOfCellsHidden;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Recalculate indexPath based on hidden cells
indexPath = [self offsetIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (NSIndexPath*)offsetIndexPath:(NSIndexPath*)indexPath
{
int offsetSection = indexPath.section; // Also offset section if you intend to hide whole sections
int numberOfCellsHiddenAbove = ... // Calculate how many cells are hidden above the given indexPath.row
int offsetRow = indexPath.row + numberOfCellsHiddenAbove;
return [NSIndexPath indexPathForRow:offsetRow inSection:offsetSection];
}
Si su tabla tiene varias secciones o las celdas tienen alturas diferentes, debe anular más métodos. Aquí se aplica el mismo principio: debe compensar indexPath, section y row antes de delegar en super.
También tenga en cuenta que el parámetro indexPath para métodos como didSelectRowAtIndexPath:
será diferente para la misma celda, dependiendo del estado (es decir, el número de celdas ocultas). Entonces, probablemente sea una buena idea compensar siempre cualquier parámetro indexPath y trabajar con estos valores.
2. Anima el cambio
Como Gareth ya lo mencionó, usted obtiene fallas importantes si anima los cambios usando el reloadSections:withRowAnimation:
.
Descubrí que si llamas a reloadData:
inmediatamente después, la animación ha mejorado mucho (solo faltan algunos fallos). La tabla se muestra correctamente después de la animación.
Entonces, lo que estoy haciendo es:
- (void)changeState
{
// Change state so cells are hidden/unhidden
...
// Reload all sections
NSIndexSet* reloadSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self numberOfSectionsInTableView:tableView])];
[tableView reloadSections:reloadSet withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadData];
}
Para el escenario más sencillo cuando oculta celdas en la parte inferior de la vista de tabla, puede ajustar el contentInset de tableView después de ocultar la celda:
- (void)adjustBottomInsetForHiddenSections:(NSInteger)numberOfHiddenSections
{
CGFloat bottomInset = numberOfHiddenSections * 44.0; // or any other ''magic number
self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, -bottomInset, self.tableView.contentInset.right);
}
Para ocultar celdas estáticas en UITable:
- Agrega este método :
En su clase de delegado del controlador UITableView:
C objetivo:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if(cell == self.cellYouWantToHide)
return 0; //set the hidden cell''s height to 0
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
Rápido:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
Se llamará a este método para cada celda en UITable. Una vez que lo llama para la celda que desea ocultar, establecemos su altura en 0. Identificamos la celda objetivo creando una salida para ella:
- En el diseñador, cree una salida para la (s) celda (s) que desea ocultar. La salida para una de esas celdas se llama "cellYouWantToHide" arriba.
- Marque "Subvistas de clips" en el IB para las celdas que desea ocultar. Las celdas que está ocultando necesitan tener ClipToBounds = YES. De lo contrario, el texto se acumulará en UITableView.
Respuesta rápida :
Agregue el siguiente método en su TableViewController:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
si el tableView intenta dibujar la celda que desea ocultar, no la mostrará porque su altura se establecerá en 0pt gracias al método anterior, todo lo demás permanece inalterado.
Tenga en cuenta que indexPathOfCellYouWantToHide
se puede cambiar en cualquier momento :)
Resulta que puede ocultar y mostrar celdas en una UITableView estática y con animación. Y no es tan difícil de lograr.
Video del proyecto de demostración
La esencia:
-
Use tableView:heightForRowAtIndexPath:
para especificar alturas de celda de forma dinámica en función de algún estado. - Cuando el estado cambia las celdas animadas que muestran
tableView.beginUpdates();tableView.endUpdates()
ocultan llamando atableView.beginUpdates();tableView.endUpdates()
- No llame a
tableView.cellForRowAtIndexPath:
dentro detableView:heightForRowAtIndexPath:
Use indexPaths en caché para diferenciar las celdas. - No escondas las celdas Establezca la propiedad "Subvistas de clip" en Xcode.
- Use celdas personalizadas (no normales, etc.) para obtener una buena animación de ocultación. Además, maneje el diseño automático correctamente para el caso cuando la altura de la celda sea == 0.
Sí, definitivamente es posible, aunque estoy luchando con el mismo problema en este momento. Logré que las celdas se ocultaran y todo funciona bien, pero actualmente no puedo hacer que la animación sea nítida. Esto es lo que he encontrado:
Estoy ocultando filas según el estado de un interruptor de ENCENDIDO / APAGADO en la primera fila de la primera sección. Si el interruptor está ENCENDIDO, hay 1 fila debajo de él en la misma sección, de lo contrario, hay 2 filas diferentes.
Tengo un selector llamado cuando el interruptor está alternado, y configuro una variable para indicar en qué estado estoy. Luego llamo:
[[self tableView] reloadData];
Sobreescribo la función tableView: willDisplayCell: forRowAtIndexPath: y si se supone que la celda está oculta, hago esto:
[cell setHidden:YES];
Eso oculta la célula y su contenido, pero no elimina el espacio que ocupa.
Para eliminar el espacio, anule la función tableView: heightForRowAtIndexPath: y devuelva 0 para las filas que deben ocultarse.
También debe anular tableView: numberOfRowsInSection: y devolver el número de filas en esa sección. Aquí tiene que hacer algo extraño, de modo que si su tabla es un estilo agrupado, las esquinas redondeadas aparecen en las celdas correctas. En mi tabla estática hay un conjunto completo de celdas para la sección, de modo que está la primera celda que contiene la opción, luego 1 celda para las opciones de estado ON y 2 celdas más para las opciones de estado OFF, un total de 4 celdas. Cuando la opción está activada, tengo que devolver 4, esto incluye la opción oculta para que la última opción que se muestra tenga un cuadro redondeado. Cuando la opción está desactivada, las dos últimas opciones no se muestran, así que regreso 2. Todo esto parece torpe. Lo siento si esto no está muy claro, es difícil de describir. Para ilustrar la configuración, esta es la construcción de la sección de la tabla en IB:
- Fila 0: Opción con interruptor de ENCENDIDO / APAGADO
- Fila 1: aparece cuando la opción está activada
- Fila 2: aparece cuando la opción está desactivada
- Fila 3: aparece cuando la opción está desactivada
Entonces, cuando la opción está en ON, la tabla informa dos filas que son:
- Fila 0: Opción con interruptor de ENCENDIDO / APAGADO
- Fila 1: aparece cuando la opción está activada
Cuando la opción está desactivada, la tabla informa cuatro filas que son:
- Fila 0: Opción con interruptor de ENCENDIDO / APAGADO
- Fila 1: aparece cuando la opción está activada
- Fila 2: aparece cuando la opción está desactivada
- Fila 3: aparece cuando la opción está desactivada
Este enfoque no se siente correcto por varias razones, es lo que tengo hasta ahora con mi experimentación, así que por favor avíseme si encuentra una mejor manera. Los problemas que he observado hasta ahora son:
Se siente mal decir a la mesa que el número de filas es diferente de lo que presumiblemente figura en los datos subyacentes.
Parece que no puedo animar el cambio. He intentado usar tableView: reloadSections: withRowAnimation: en lugar de reloadData y los resultados no parecen tener sentido, todavía estoy intentando que esto funcione. Actualmente, lo que parece suceder es que tableView no actualiza las filas correctas, por lo que queda oculto y debe aparecer un espacio vacío debajo de la primera fila. Creo que esto podría estar relacionado con el primer punto sobre los datos subyacentes.
Con suerte, alguien podrá sugerir métodos alternativos o quizás cómo extenderlos con la animación, pero quizás esto lo ayude a comenzar. Mis disculpas por la falta de hipervínculos a las funciones, las puse pero fueron rechazadas por el filtro de spam porque soy un usuario bastante nuevo.
Se me ocurrió una alternativa que en realidad oculta las secciones y no las elimina. Intenté el enfoque de @ henning77, pero me encontré con problemas cuando cambié el número de secciones de la UITableView estática. Este método me ha funcionado muy bien, pero principalmente trato de ocultar secciones en lugar de filas. Estoy eliminando algunas filas sobre la marcha con éxito, pero es mucho más complicado, así que he tratado de agrupar las cosas en secciones que necesito mostrar u ocultar. Aquí hay un ejemplo de cómo estoy ocultando secciones:
Primero declaro una propiedad NSMutableArray
@property (nonatomic, strong) NSMutableArray *hiddenSections;
En viewDidLoad (o después de haber consultado sus datos) puede agregar secciones que desea ocultar a la matriz.
- (void)viewDidLoad
{
hiddenSections = [NSMutableArray new];
if(some piece of data is empty){
// Add index of section that should be hidden
[self.hiddenSections addObject:[NSNumber numberWithInt:1]];
}
... add as many sections to the array as needed
[self.tableView reloadData];
}
A continuación, implemente los siguientes métodos delegados TableView
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return nil;
}
return [super tableView:tableView titleForHeaderInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
return 0;
}
return [super tableView:tableView heightForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
[cell setHidden:YES];
}
}
Luego configure la altura del encabezado y del pie de página en 1 para las secciones ocultas porque no puede establecer la altura en 0. Esto ocasiona un espacio adicional de 2 píxeles, pero podemos compensarlo ajustando la altura del siguiente encabezado visible.
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
CGFloat height = [super tableView:tableView heightForHeaderInSection:section];
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
height = 1; // Can''t be zero
}
else if([self tableView:tableView titleForHeaderInSection:section] == nil){ // Only adjust if title is nil
// Adjust height for previous hidden sections
CGFloat adjust = 0;
for(int i = (section - 1); i >= 0; i--){
if([self.hiddenSections containsObject:[NSNumber numberWithInt:i]]){
adjust = adjust + 2;
}
else {
break;
}
}
if(adjust > 0)
{
if(height == -1){
height = self.tableView.sectionHeaderHeight;
}
height = height - adjust;
if(height < 1){
height = 1;
}
}
}
return height;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return 1;
}
return [super tableView:tableView heightForFooterInSection:section];
}
Luego, si tiene filas específicas para ocultar, puede ajustar numberOfRowsInSection y qué filas se devuelven en cellForRowAtIndexPath. En este ejemplo, aquí tengo una sección que tiene tres filas donde las tres pueden estar vacías y deben eliminarse.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = [super tableView:tableView numberOfRowsInSection:section];
if(self.organization != nil){
if(section == 5){ // Contact
if([self.organization objectForKey:@"Phone"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"Email"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"City"] == [NSNull null]){
rows--;
}
}
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [super tableView:tableView cellForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
Utilice este offsetIndexPath para calcular el indexPath para las filas en las que está eliminando filas de forma condicional. No es necesario si solo está ocultando secciones
- (NSIndexPath *)offsetIndexPath:(NSIndexPath*)indexPath
{
int row = indexPath.row;
if(self.organization != nil){
if(indexPath.section == 5){
// Adjust row to return based on which rows before are hidden
if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
else if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Address"] != [NSNull null]){
row = row + 2;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] != [NSNull null] && [self.organization objectForKey:@"Email"] == [NSNull null]){
row++;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
}
}
NSIndexPath *offsetPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section];
return offsetPath;
}
Hay muchos métodos para anular, pero lo que me gusta de este enfoque es que es reutilizable. Configure la matriz hiddenSections, añádala y ocultará las secciones correctas. Esconder las filas es un poco más complicado, pero posible. No podemos simplemente establecer la altura de las filas que queremos ocultar en 0 si estamos usando una UITableView agrupada porque los bordes no se dibujarán correctamente.
Según la respuesta de Justas, pero para Swift 4:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
Seguramente tu puedes Primero, regrese a su tabla. Vea el número de celdas que desea mostrar y luego llame a super
para obtener cierta celda de su guión gráfico y devuélvala para tableView:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.mode.numberOfCells()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
return cell
}
Si sus celdas tienen diferente altura, devuélvala también:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
}
Usted está buscando esta solución:
StaticDataTableViewController 2.0
https://github.com/xelvenone/StaticDataTableViewController
que puede mostrar / ocultar / recargar cualquier celda estática con o sin animación!
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
Nota para usar siempre solo (reloadDataAnimated: YES / NO) (no llame [self.tableView reloadData] directamente)
Swift 4:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var height = super.tableView(tableView, heightForRowAt: indexPath)
if (indexPath.row == HIDDENROW) {
height = 0.0
}
return height
}