2010-03-22 3 views
22

У меня есть сгруппированный UITableView, где не все секции могут отображаться сразу, таблица управляется некоторыми данными, которые не каждая запись может иметь. Моя беда в том, что записи, которые не имеют определенные разделы отображаются как пустые места в таблице (см рисунка)Сгруппированный UITableView показывает пустое место, когда раздел пуст

alt text http://img220.imageshack.us/img220/5633/screenshot20100322at228.png

Там нет колонтитулов/заголовков. Все, что я пропустил?

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
// Return the number of rows in the section. 
return [self getRowCount:section]; 
} 


// Customize the appearance of table view cells. 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

static NSString *CellIdentifier = @"Cell"; 

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
} 

cell.textLabel.text = [NSString stringWithFormat:@"section: %d row: %d",indexPath.section,indexPath.row]; 
// Configure the cell... 

return cell; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 

    float height = 0.0; 

    if([self getRowCount:indexPath.section] != 0){ 
     height = kDefaultRowHeight; 
    } 

    return height; 

} 

ответ

6

В приведенном выше скриншоте, ваш numberOfSectionsInTableView: метод возвращает значение 5? А затем ваш метод getRowCount: (вызванный от numberOfRowsInSection:), возвращающий значение 0 для этих «отсутствующих» разделов (например, 1, 3 и 4)?

Если вам не нужны промежутки между ними, вероятное решение состоит в том, чтобы объявлять только количество разделов, которые вы хотите видеть. В приведенном выше примере вам нужно только вернуть значение 3 из numberOfSectionsInTableView:.

0

Я считаю, что при просмотре таблиц разделов каждый раздел должен существовать, и каждый раздел имеет буферную комнату для заголовка и нижнего колонтитула, независимо от того, вставляете ли вы текст в них. Вам нужно удалить разделы, которые не используются. В вашем примере, вы бы удалить раздел 1, 3 и 4. Это будет означать:

"раздел 0" является indexPath.section == 0

"Раздел 2" является indexPath.section == 1

«раздел 5» является indexPath.section == 2

Если код таким образом, верхние и нижние колонтитулы будут удалены, так как ноль клеток удаляется.

Это не правильное кодирование, но я просто хотел дать вам представление о богословии. Надеюсь, это поможет.

38

У меня подобная ситуация, и моя модель данных действительно работает лучше, если я могу позволить ей иметь пустые разделы.

Ваша проблема может быть решена, если вы установили self.tableView.sectionHeaderHeight = 0; и self.tableView.sectionFooterHeight = 0; в свой контроллер таблицы. Они должны быть 0, потому что методы делегируют как-то игнорировать возвращаемое значение 0. Тогда вы должны переопределить некоторые методы делегата:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
    if (section==0) 
     return sectionGapHeight; 
    if ([self tableView:tableView numberOfRowsInSection:section]==0) { 
     return 0; 
    } 
    return sectionGapHeight; 
} 
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
    if (section==[self numberOfSectionsInTableView:tableView]-1) { 
     return sectionGapHeight; 
    } 
    return 0; 
} 
- (UIView *)sectionFiller { 
    static UILabel *emptyLabel = nil; 
    if (!emptyLabel) { 
     emptyLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 
     emptyLabel.backgroundColor = [UIColor clearColor]; 
    } 
    return emptyLabel; 
} 
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 
    return [self sectionFiller]; 
} 
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { 
    return [self sectionFiller]; 
} 

Этот код будет также сделать разрыв между секциями ту же высоту, что и зазор перед первым и промежуток ниже последнего. Это выглядит лучше, по моему мнению, чем по умолчанию, где разрыв между ними вдвое больше, чем у верхнего и нижнего.

+0

Nice, спасибо за следственную работу! –

+3

Наименее навязчивый метод, который я нашел до сих пор, - это вернуть 1 для heightForHeaderInSection и heightForFooterInSection 'if ([self tableView: tableView numberOfRowsInSection: section] == 0)' и вернуть представление с нулевым размером для 'viewForHeaderInSection' /' viewForFooterInSection 'если количество строк равно 0. –

+1

Спасибо! Благодаря! Внезапное яблоко. Было бы очень приятно, если бы они задокументировали такие вещи, как то, что возвращение 0 для высот в делегате не отменяет стандартного интервала. Есть слишком много тонких случаев API, которые Apple не документирует. – smparkes

4

Это решение основано на запросе пользователя362178.Но хранит метки разделов нетронутыми:

Определить где-то в верхней части кода:

#define HEIGHT_FOR_HEADER_AND_FOOTER 50 

Добавить к мнению сделал груз:

self.tableView.sectionHeaderHeight = 0; 
self.tableView.sectionFooterHeight = 0; 

Добавьте следующие методы:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
{ 
    // Needed because if this does not return a value, the header label of the section will 
    // be at the top of the screen. 
    if (section == 0) 
    { 
     return HEIGHT_FOR_HEADER_AND_FOOTER; 
    } 

    if ([self tableView:tableView numberOfRowsInSection:section] == 0) 
    { 
     return 0; 
    } 
    else 
    { 
     return HEIGHT_FOR_HEADER_AND_FOOTER; 
    } 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section 
{ 
    // if last section 
    if (section == [self numberOfSectionsInTableView:tableView] - 1) 
    { 
     return HEIGHT_FOR_HEADER_AND_FOOTER; 
    } 

    return 0; 
} 
17

Вот решение, которое сработало для меня

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
    switch (section) { 
     case 1: case 3: case 5: return 20.0f; break; 
     default: return 0.01f; // for some reason 0 is not accepted - give something :) 
    } 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
    switch (section) { 
     case 1: case 3: case 5: return 20.0f; break; 
     default: return 0.01f; // for some reason 0 is not accepted - give something :) 
    } 
} 
+1

Я прочитал это и подумал: «Нет, это просто не нравится 0.0f». Но я проверил это, и с iOS6 это все еще так. –

+0

Даже на iOS 8, 0 не accepter, но 0.01f есть :-) –

0

Ключом является установка sectionHeaderHeight и sectionFooterHeight в виде таблицы.

Вы можете сделать это либо в viewDidLoad, либо в Пользовательских атрибутах Runtime в вашей раскадровке/xib. По какой-то причине на вкладке «Размер инспектора» вы не можете установить высоту заголовка или нижнего колонтитула ниже 1.

Я обнаружил, что как только я это сделал, мне не нужно было переопределять какие-либо другие методы делегата особым образом. Я просто возвращаю 0 от numberOfRowsInSection и nil от titleForHeaderInSection для разделов, которые пусты, и они не занимают места в моем представлении таблицы.

У разделов, имеющих названия, автоматически присваивается соответствующий размер заголовка, а верхняя часть представления таблицы по-прежнему имеет пустое место по умолчанию.

1

Я имел такую ​​же проблему прошивкой 7 и, наконец, я решил эту проверку высоты для секций верхнего и нижнего колонтитула, так как Рамеш сказал:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
if ([[self.tableView objectAtIndex:section] count] == 0) 
    return 0.01f; 
else 
    return 30.f; 

}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
return 0.01f; 

}

Это любопытно, но если вы установите 0.f как высоту, разделы показываются с размером по умолчанию и перемещаются вниз по другим разделам.

1

Вот самый элегантное решение, которое я нашел на основе всех ответов здесь, плюс this answer:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 

    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) { 
     return nil; 
    } else { 
     // Return title normally 
    } 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
    if ([self tableView: tableView numberOfRowsInSection: section] == 0) { 
     return 0.01f;; 
    } 

    return UITableViewAutomaticDimension; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
    if ([self tableView: tableView numberOfRowsInSection: section] == 0) { 
     return 0.01f;; 
    } 

    return UITableViewAutomaticDimension; 
}