2009-09-06 2 views
20

У меня есть UITableView, где в некоторых случаях определенные разделы имеют нулевые строки. Моя цель состоит в том, что, когда это правда, я не хочу потерять пространство в представлении таблицы, это должно выглядеть так, как будто нет данных.UITableView Не уважаемая высотаForHeaderInSection/heightForFooterInSection?

Проблема, с которой я столкнулся, - это заголовок и нижний колонтитул для разделов, которые отображаются, даже если нет строки и, несмотря на то, что я переопределяю метод делегата, чтобы вернуть 0.0f.

Вот как это выглядит: вы можете увидеть ~ 20p серого пространства наверху, верхние и нижние колонтитулы около 10p для секции с 0 строками.

alt text http://www.hanchorllc.com/table_cells.png

Вот мой псевдо-код:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
    if ([section hasRow]) { 
      return 10.0f; 
    } else { 
      return 0.0f; 
    } 
} 



- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
    if ([section hasRow]) { 
      return 10.0f; 
    } else { 
      return 0.0f; 
    } 
} 

Я проверил, что эти методы называют и что надлежащее исполнение путь проходит.

Один морщин - этот контроллер вида использует XIB и что UITableView имеет значения заголовка и нижнего колонтитула раздела, установленные в 10.0 (по умолчанию), хотя я думал, что это было переопределено методом делегата, если оно реализовано.

Это приложение, ориентированное на 3.0.

Что я делаю неправильно?

ответ

24

В «сгруппированном» UITableView на iPhone он по-прежнему будет отображать минимальную высоту для верхнего и нижнего колонтитулов, эффективно игнорируя ваш код, чтобы установить его на ноль. Он не связан с положением XIB.

Это потому, что верхний или нижний колонтитул с нулевой высотой будет выглядеть очень странно. Поэтому Apple постановила, что высота заголовка не может быть установлена ​​на 0. И поэтому несколько «пустых» разделов будут отображаться странно в соответствии с вашим снимком экрана.

Я боюсь, что это все, потому что вы ошибетесь в том, чтобы очистить размер заголовка, когда нет строк данных; вместо этого вы должны не вызывать никаких методов для пустых разделов. Это плохой метод, потому что, по сути, iPhone должен вызывать больше методов, чем следовало бы, а также отображать больше заголовков, чем вы хотите (обычно - иногда люди хотят оставить пустые заголовки там, например, для перетаскивания) ,

Итак, предположим, что у вас есть несколько разделов, но только некоторые из них имеют более одной строки (возможно, на основе пользовательских настроек/фильтров).

неправильно способ ее реализации является:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return totalNumberOfPossibleSections; 
} 

, а затем для каждого раздела у вас нет результата для:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    if (![section hasRow]) return 0; 
} 

и

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
    if (![section hasRow]) return 0.0f; 
} 

правильно Способ применения приклеивание:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return numberOfSectionsWhichHaveAtLeastOneRowInThem; 
} 

, а затем каждый раздел будет иметь как минимум один результат.Таким образом, разделы без данных даже не отображаются, методы даже не называются для них. Примечание: мои два имени переменной составлены, чтобы передать то, что они будут содержать! Они не являются специальными переменными Apple ...

Надеюсь, что это поможет!

+0

Да, это звучит разумно. У меня появилась привычка объявлять константы перечисления для макетов разделов таблицы, и я пытался заставить этот конкретный контроллер использовать этот дизайн, который не очень хорошо работает с неизвестным количеством строк в разделах. Нечетно, что документация Apple не указывает нигде (что я могу найти), что она не будет принимать значение 0.0 в качестве значения, тем более, что вы * можете * установить 0.0 в XIB (и да, это выглядит действительно странно). Я могу записать ошибку doco, поскольку по крайней мере следует отметить, что значение должно быть больше 0.0f. Cheers. – Hunter

+0

Это действительно выглядит странно - я также не видел его ни в одной из документации, поэтому, вероятно, стоит записать это как ошибку. – h4xxr

+0

Это хорошая идея, но у меня были проблемы с ее внедрением. У меня есть инструкции switch для раздела в связке моих методов tableview. Возвращение переменной количества разделов в зависимости от содержимого данных действительно испортит это сопоставление, и я не могу придумать элегантный (или даже простой) способ справиться с этим. – blindjesse

0

Собственно, со мной это происходит наоборот. Я назначил заголовок раздела равным 10 в xib, но для первого раздела я хочу заголовок заголовка размера. Я использую этот метод в моем UITableViewCotroller

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if(indexPath.section==0) 
     return 125; 
    return tableView.rowHeight; 
} 

Но высота заголовка раздела не изменяются, даже если метод вызывался.

3

У меня была аналогичная проблема: я загружая UITableView из XIB (такой же, как вы), и поставила 0 высоту для некоторых секций колонтитулы с tableView:heightForFooterInSection (такой же, как вы), но значение игнорируется.

Исправление было простым: также установите высоту нижнего колонтитула 0.0 в XIB. (В построителе интерфейса выберите «Вид таблицы», нажмите «Command-3», чтобы просмотреть «Инспектор размеров», найдите верхнее поле нижнего колонтитула вверху).

После того, как это было сделано, он выполнил высоту пользовательского нижнего колонтитула, как ожидалось. (Возможно, он рассматривает высоту нижнего колонтитула XIB как минимум?)

+0

В IB минимальная высота сечения, которую вы можете установить для сгруппированного представления таблицы, равна 1. Таким образом, это ничего не меняет. –

1

Это работает для меня:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
{ 
    tableView.sectionHeaderHeight = (section == 0 ? 10 : 0); 
    return tableView.sectionHeaderHeight; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section 
{ 
    tableView.sectionFooterHeight = (section == 0 ? 20 : 4); 
    return tableView.sectionFooterHeight; 
} 
9

Оказывается, что таблица уважает tableView:heightForHeaderInSection: только если tableView:viewForHeaderInSection: не nil, или если tableView:titleForHeaderInSection: не nil или @"". То же самое верно для высот нижнего колонтитула.

Так если вы не имеете каких-либо видов заголовка раздела или названия, просто добавьте в ваш стол делегата:

- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 
    return [[[UIView alloc] initWithFrame:CGRectZero] autorelease]; 
} 
+0

Это неправда.Если вы вернете 0 в tableView: heightForHeaderInSection :, вы получите нижний колонтитул в 10 точек. Вам нужно будет указать немного большее число, например 0,00001f, как @Juris упоминает в своем ответе. – Klaas

0

Мое решение этой проблемы и выключаться, как h4xxr описывает, однако, у меня есть несколько иной подход к построению динамического числа разделов.

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

Предположим, что мой первый раздел - это контактные данные с указанием имени, фамилии и возраста. Я определю этот раздел с идентификатором «1» (хотя технически, как я объясню позже, это может быть любое число). Теперь, если мой метод определяет, что этот раздел должен быть видимым, я нажимаю значение '1' на массив.

Следующий раздел, который я хочу показать, это адрес и может содержать 3-4 строки/ячейки. Как и выше, логика в моем методе определяет, должен ли адрес быть видимым, нажимая «2» на массив.

Теперь .. ..если мы хотели, чтобы обе секции были видимыми, у нас был бы массив с длиной 2 и двумя элементами [1,2]. Если бы мы хотели, чтобы информация о контакте была видимой, наш массив имел бы длину 1 с элементами [1] и [2] только для адреса.

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

наш переключатель заявление будет выглядеть как-то вроде этого:

switch(ourArray[indexPath.section]){ 
    case 1: 
     <Return the number of rows for the contact details which we said would be 3> 
     break; 
    case 2: 
     <Return the number of rows for the address details which we said would be 4> 
     break; 
    case 3: 
     <Return another number for some section that is referenced by the id '3'> 
     break; 
} 

Обратите внимание, я поставил корпус 3 в моем переключателе. Поскольку массив в нашем примере содержит только значения «1» и «2», случай 3 никогда не будет сопоставляться и поэтому игнорируется, если мы не решили добавить/включить этот случай, нажав его на массив.

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

Я использую вышеупомянутое религиозно, так как это позволяет мне отделить индексирование и строительство секций.

Наконец, перед тем, как обновить таблицу, используя 'reloadData', я вызову свой метод, который построит массив и предоставит правильную длину и последовательность идентификаторов раздела, чтобы позволить моему tableview знать, как построить себя. Если мои данные каким-либо образом меняются или фильтруются, я снова вызову этот метод и восстановим массив.

32

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

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 
    if(section == 1) 
     return 0.000001f; 
    else return 44.0f; // put 22 in case of plain one.. 
} 

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ 
    return 0.000001f; //removing section footers 
} 
+0

Ничего себе. Это так сложно, но это работает. – nonamelive

+1

Этот хак, похоже, не работает на iOS 7. – crishoj

+1

Один из трюков. После траты дня на высотеForHeaderInSection и heightForFooterInSection это сработало для меня. И работает и на iOS 7 :) – Machete

1

я обнаружил, что в моем случае были необходимы 2 вещи, чтобы убить фантомное колонтитула:

1) определение вида таблицы sectionFooterHeight к 0, т.е. в viewDidLoad добавления:

tableView.sectionFooterHeight = 0 

2), добавив делегатский метод:

(с использованием Swift 2.2)