Можно ли отключить плавающие заголовки в UITableView с помощью UITableViewStylePlain?

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

Другой, используя UITableViewStyleGrouped , есть ли способ сделать это? Я бы хотел избежать группировки, поскольку он добавляет разницу по всем моим ячейкам и требует отключения фонового представления для каждой из ячеек. Я бы хотел полностью контролировать мой макет. В идеале они были бы «UITableViewStyleBareBones», но я не видел этого параметра в документах …

Большое спасибо,

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

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

Вам, вероятно, придется самостоятельно управлять своими разделами, т. Е. Иметь все в одном разделе и подделывать заголовки. (Вы также можете попробовать вернуть скрытый вид для заголовка, но я не знаю, будет ли это работать)

Вероятно, более простой способ добиться этого:

Objective-C:

 CGFloat dummyViewHeight = 40; UIView *dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, dummyViewHeight)]; self.tableView.tableHeaderView = dummyView; self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0); 

Swift:

 let dummyViewHeight = CGFloat(40) self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight)) self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0) 

Заголовки разделов теперь будут прокручиваться точно так же, как и любая обычная ячейка.

Изменить стиль таблицы от простого к сгруппированному (для тех, кто когда-либо попал сюда из-за неправильного стиля таблицы)

 let tableView = UITableView(frame: .zero, style: .grouped) 

ПРЕДУПРЕЖДЕНИЕ : это решение реализует зарезервированный метод API. Это может помешать утверждению Apple Apple для распространения в AppStore.

Я описал частные методы, которые превращают заголовки разделов, плавающие в моем блоге

В принципе, вам просто нужно подclassифицировать UITableView и возвращать NO в двух своих методах:

 - (BOOL)allowsHeaderViewsToFloat; - (BOOL)allowsFooterViewsToFloat; 

Хорошо, я знаю, что поздно, но я должен был это сделать. Я потратил 10 часов на поиски рабочего решения, но не нашел полного ответа. Нашел некоторые намеки, но трудно понять начинающим. Так что я должен был поставить свои 2 цента и выполнить ответ.

Как было предложено в нескольких ответах, единственным рабочим решением, которое я смог реализовать, является вставка нормальных ячеек в представление таблицы и обработка их как заголовков секторов, но лучший способ добиться этого – вставить эти ячейки в строка 0 каждого раздела. Таким образом, мы можем легко справиться с этими настраиваемыми неплавающими заголовками.

Итак, шаги.

  1. Внедрите UITableView со стилем UITableViewStylePlain.

     -(void) loadView { [super loadView]; UITableView *tblView =[[UITableView alloc] initWithFrame:CGRectMake(0, frame.origin.y, frame.size.width, frame.size.height-44-61-frame.origin.y) style:UITableViewStylePlain]; tblView.delegate=self; tblView.dataSource=self; tblView.tag=2; tblView.backgroundColor=[UIColor clearColor]; tblView.separatorStyle = UITableViewCellSeparatorStyleNone; } 
  2. Реализуйте titleForHeaderInSection как обычно (вы можете получить это значение, используя свою собственную логику, но я предпочитаю использовать стандартные delegates).

     - (NSString *)tableView: (UITableView *)tableView titleForHeaderInSection:(NSInteger)section { NSString *headerTitle = [sectionArray objectAtIndex:section]; return headerTitle; } 
  3. Внедрение numberOfSectionsInTableView как обычно

     - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { int sectionCount = [sectionArray count]; return sectionCount; } 
  4. Реализуйте numberOfRowsInSection, как обычно.

     - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { int rowCount = [[cellArray objectAtIndex:section] count]; return rowCount +1; //+1 for the extra row which we will fake for the Section Header } 
  5. Верните 0.0f в heightForHeaderInSection.

     - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 0.0f; } 
  6. НЕ реализуйте viewForHeaderInSection. Удалите метод полностью, вместо того, чтобы возвращать нуль.

  7. В heightForRowAtIndexPath. Проверьте if (indexpath.row == 0) и верните желаемую высоту ячейки для заголовка раздела, иначе верните высоту ячейки.

     - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if(indexPath.row == 0) { return 80; //Height for the section header } else { return 70; //Height for the normal cell } } 
  8. Теперь в cellForRowAtIndexPath проверьте if (indexpath.row == 0) и реализуйте ячейку так, как вам нужен заголовок раздела, и установите для стиля выбора значение none. ELSE реализует ячейку, как вы хотите, чтобы нормальная ячейка была.

     - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 0) { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SectionCell"]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SectionCell"] autorelease]; cell.selectionStyle = UITableViewCellSelectionStyleNone; //So that the section header does not appear selected cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SectionHeaderBackground"]]; } cell.textLabel.text = [tableView.dataSource tableView:tableView titleForHeaderInSection:indexPath.section]; return cell; } else { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"] autorelease]; cell.selectionStyle = UITableViewCellSelectionStyleGray; //So that the normal cell looks selected cell.backgroundView =[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"CellBackground"]]autorelease]; cell.selectedBackgroundView=[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SelectedCellBackground"]] autorelease]; } cell.textLabel.text = [[cellArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row -1]; //row -1 to compensate for the extra header row return cell; } } 
  9. Теперь реализуем willSelectRowAtIndexPath и возвращаем nil, если indexpath.row == 0. Это будет зависеть от того, что didSelectRowAtIndexPath никогда не запускается для строки заголовка раздела.

     - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 0) { return nil; } return indexPath; } 
  10. И, наконец, в файле didSelectRowAtIndexPath проверьте if (indexpath.row! = 0) и продолжайте.

     - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row != 0) { int row = indexPath.row -1; //Now use 'row' in place of indexPath.row //Do what ever you want the selection to perform } } 

С этим вы закончили. Теперь у вас есть совершенно прокручиваемый, неплавающий заголовок раздела.

В своем интерфейсе Builder нажмите на свою проблему.

вид таблицы задач

Затем перейдите к Attributes Inspector и измените Style Plain на Grouped;) Easy

легко

Интересная вещь в UITableViewStyleGrouped заключается в том, что tableView добавляет стиль в ячейки, а не в TableView.

Стиль добавляется как backgroundView в ячейки как class UIGroupTableViewCellBackground, который обрабатывает рисунок другого фона в соответствии с положением ячейки в этом разделе.

Поэтому очень простым решением будет использование UITableViewStyleGrouped, установка backgroundColor таблицы clearColor и просто замена backgroundView ячейки в cellForRow:

 cell.backgroundView = [[[UIView alloc] initWithFrame:cell.bounds] autorelease]; 

Измените стиль TableView:

 self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped]; 

Согласно документации Apple для UITableView:

UITableViewStylePlain – представление в виде простой таблицы. Любые верхние или нижние колонтитулы разделов отображаются в виде встроенных разделителей и плавают при прокрутке вида таблицы.

UITableViewStyleGrouped – представление таблицы, в разделах которого представлены различные группы строк. Верхние и нижние колонтитулы не плавают.

Надеюсь, это небольшое изменение поможет вам.

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

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return sectionCount * 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section%2 == 0) { return 0; } return _rowCount; } 

Что нужно сделать, так это реализовать delegates headerInSection:

 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { if (section%2 == 0) { //return headerview; } return nil; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { if (section%2 == 0) { //return headerheight; } return 0; } 

Этот подход также мало влияет на ваши источники данных:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { int real_section = (int)indexPath.section / 2; //your code } 

Сравнивая с другими подходами, этот способ безопасен, не изменяя frameworks или contentInsets таблицы. Надеюсь, это поможет.

Самый простой способ получить то, что вам нужно, – установить стиль таблицы как UITableViewStyleGrouped , стиль разделителя как UITableViewCellSeparatorStyleNone :

 - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return CGFLOAT_MIN; // return 0.01f; would work same } - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { return [[UIView alloc] initWithFrame:CGRectZero]; } 

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

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

Подумав, как подойти к этой проблеме, я вспомнил очень важную информацию о UITableViewStyleGrouped. Способ, которым UITableView реализует сгруппированный стиль (округленные границы вокруг ячеек), заключается в добавлении настраиваемого backgroundView в UITableViewCells, а не в UITableView. Каждая ячейка добавляет backgroundView в соответствии с ее положением в секции (верхние ряды получают верхнюю часть границы раздела, а средние получают боковую границу, а нижняя – – ну, нижняя часть). Итак, если мы просто хотим простой стиль, и у нас нет пользовательского backgroundView для наших ячеек (что происходит в 90% случаев), тогда нам нужно всего лишь использовать UITableViewStyleGrouped и удалить настраиваемый фон , Это можно сделать, выполнив следующие два шага:

Измените наш стиль tableView на UITableViewStyleGrouped Добавьте следующую строку в cellForRow, перед тем как вернуть ячейку:

cell.backgroundView = [[[UIView alloc] initWithFrame: cell.bounds] autorelease];

Вот и все. Стиль tableView станет точно таким же, как UITableViewStylePlain, за исключением плавающих заголовков.

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

Для Swift 3+

Просто используйте UITableViewStyleGrouped и установите высоту UITableViewStyleGrouped колонтитула равным нулю:

 override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { return .leastNormalMagnitude } 

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

Вы можете добавить один раздел (с нулевыми строками) выше, а затем установить вышеуказанный разделFooterView в качестве заголовка текущего раздела, footerView не плавает. Надеюсь, что это поможет.

Возможно, вы можете использовать scrollViewDidScroll в tableView и изменить contentInset на основе текущего видимого заголовка.

Кажется, это работает для моего использования!

 extension ViewController : UIScrollViewDelegate{ func scrollViewDidScroll(_ scrollView: UIScrollView) { guard let tableView = scrollView as? UITableView, let visible = tableView.indexPathsForVisibleRows, let first = visible.first else { return } let headerHeight = tableView.rectForHeader(inSection: first.section).size.height let offset = max(min(0, -tableView.contentOffset.y), -headerHeight) self.tableView.contentInset = UIEdgeInsetsMake(offset, 0, -offset, 0) } } 

Игнорировать XAK. Не изучайте какие-либо частные методы, если вы хотите, чтобы ваше приложение могло быть принято яблоком.

Это проще всего, если вы используете Interface Builder. Вы должны добавить UIView в верхней части представления (куда будут идти изображения), а затем добавить таблицу ниже. IB должен соответствующим образом измерять его; то есть верхняя часть таблицы просматривает нижнюю часть UIView, которую вы только что добавили, и ее высота покрывает остальную часть экрана.

Мысль здесь состоит в том, что если этот UIView фактически не является частью представления таблицы, он не будет прокручиваться с помощью tableview. т.е. игнорировать заголовок таблицы.

Если вы не используете построитель интерфейсов, это немного сложнее, потому что вам нужно получить правильное позиционирование и высоту таблицы.

Это может быть достигнуто путем назначения заголовка вручную в методе viewDidLoad UITableViewController вместо использования представления делегата forHeaderInSection и heightForHeaderInSection. Например, в вашем подclassе UITableViewController вы можете сделать что-то вроде этого:

 - (void)viewDidLoad { [super viewDidLoad]; UILabel *headerView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 40)]; [headerView setBackgroundColor:[UIColor magentaColor]]; [headerView setTextAlignment:NSTextAlignmentCenter]; [headerView setText:@"Hello World"]; [[self tableView] setTableHeaderView:headerView]; } 

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

Проверьте ответ, как реализовать заголовки со StoryBoard: просмотры заголовков таблиц в StoryBoards

Также обратите внимание, что если вы не реализуете

 viewForHeaderInSection:(NSInteger)section 

он не будет плавать, что именно вы хотите.

Чтобы полностью удалить разделы заголовка плавающего раздела, вы можете сделать это:

 - (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { return [[UIView alloc] init]; } 

return nil не работает.

Чтобы отключить плавающие, но все еще отображаемые заголовки разделов, вы можете создать собственное представление с собственным поведением.

Возможно, вы можете просто сделать прозрачный вид заголовка:

 - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { view.tintColor = [UIColor clearColor]; } 

Или примените его по всему миру:

  [UITableViewHeaderFooterView appearance].tintColor = [UIColor clearColor]; 

Согласно ответу @ samvermette, я внедрил приведенный выше код в Swift, чтобы упростить для кодеров использование swift.

 let dummyViewHeight = CGFloat(40) self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight)) self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0) 

ref: https://stackoverflow.com/a/26306212

let tableView = UITableView(frame: .zero, style: .grouped)

Pluse

 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { if section == 0 { return 40 }else{ tableView.sectionHeaderHeight = 0 } return 0 } 

Это помогло использовать пространство заголовка

У меня есть еще одно более простое решение, которое можно использовать без автозапуска и со всем, что делается через XIB:

1 / Поместите свой заголовок в tableview, перетащив его непосредственно в tableview.

2 / В инспекторе размеров недавно созданного заголовка просто измените его автоматизацию: вы должны оставить только верхний, левый и правый анкеры, а также заполнить по горизонтали.

Вот как это должно быть настроено для заголовка

Это должно делать свое дело !

вы можете легко достичь этого, реализовав метод viewForHeaderInSection в classе делегата tableview. этот метод ожидает UIView как объект возврата (который является вашим представлением заголовка). я сделал то же самое в своем коде

  • AppDelegate, rootViewController и presentViewController
  • Как найти причину ошибки «double free» malloc?
  • Какова максимальная длина объекта NSString?
  • Как я могу получить точное время, например, в миллисекундах в Objective-C?
  • Как получить размер UIKeyboard с Apple iPhone SDK
  • Как я могу программно проверить, присутствует ли клавиатура в приложении iOS?
  • Может ли iPhone приложение блокировать телефонные звонки?
  • Можем ли мы пригласить людей использовать наше приложение или отправить запрос друга из приложения через Facebook в iOS 5?
  • Как я могу перебирать все подпункты UIView, а также их подзоны и их подпрограммы
  • Программно извлекать использование памяти на iPhone
  • Как отобразить изображение base64 в UIImageView?
  • Давайте будем гением компьютера.