Как скрыть заголовок первого раздела в UITableView (сгруппированный стиль)

108

Поскольку дизайн представлений таблиц с использованием сгруппированного стиля значительно изменился в iOS 7, я хотел бы скрыть (или удалить) заголовок первого раздела. Пока мне этого не удалось.

В несколько упрощенном виде мой код выглядит так:

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 0)
        return 0.0f;
    return 32.0f;
}

- (UIView*) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        UIView* view = [[UIView alloc] initWithFrame: CGRectMake(0.0f, 0.0f, 640.0f, 0.0f)];
        return view;
    }
    return nil;
}

- (NSString*) tableView:(UITableView *) tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return nil;
    } else {
        // return some string here ...
    }
}

Если я верну высоту, равную 0, два других метода никогда не будут вызываться с индексом раздела 0. Тем не менее, пустой заголовок раздела все еще отображается с высотой по умолчанию. (В iOS 6 вызываются два метода. Однако видимый результат тот же.)

Если я верну другое значение, заголовок раздела получит указанную высоту.

Если я верну 0,01, это почти правильно. Однако, когда я включаю «Цвет несогласованных изображений» в симуляторе, он отмечает все ячейки табличного представления (что кажется логическим следствием).

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

На данный момент лучшим компромиссом является возврат высоты 0,5, в результате чего линия под панелью навигации будет несколько более толстой. Однако я был бы признателен, если бы кто-нибудь знал, как можно полностью скрыть заголовок первого раздела.

Обновить

Согласно анализу Каглара ( https://stackoverflow.com/a/19056823/413337 ), проблема возникает только в том случае, если представление таблицы содержится в контроллере навигации.

Кодо
источник
Я не понял эту часть => if (section == 0) return view; вернуть ноль; т.е. возврат представления, когда это первый раздел, и ноль в противном случае?
Zen
Идея состоит в том, чтобы вернуть представление с высотой 0 для первого раздела и вернуть nil для всех остальных разделов, чтобы представление таблицы использовало для них представление заголовка по умолчанию. Ноль часть хорошо работает; в виде таблицы отображается заголовок для этих разделов. Но часть для раздела 0 не имеет значения, потому что метод никогда не вызывается с помощью section == 0.
Codo
1
Этот ответ кажется коротким и приятным. stackoverflow.com/a/23955420/3965
Мистер Роджерс

Ответы:

154

У меня есть обходной путь, который мне кажется достаточно чистым. Итак, я отвечаю на свой вопрос.

Поскольку 0 в качестве высоты заголовка первого раздела не работает, я возвращаю 1. Затем я использую contentInset, чтобы скрыть эту высоту под панелью навигации.

Цель-C:

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 0)
            return 1.0f;
    return 32.0f;
}

- (NSString*) tableView:(UITableView *) tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return nil;
    } else {
        // return some string here ...
    }
}

- (void) viewDidLoad
{
    [super viewDidLoad];

     self.tableView.contentInset = UIEdgeInsetsMake(-1.0f, 0.0f, 0.0f, 0.0);
}

Swift:

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return section == 0 ? 1.0 : 32
}

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.contentInset = UIEdgeInsets(top: -1, left: 0, bottom: 0, right: 0)
}
Кодо
источник
6
Чтобы скрыть его, даже лучше использовать высоту заголовка 0,1f.
Chuck Krutsinger 01
4
Я пробовал использовать 0.1f. Но в результате рисунки больше не выравниваются по пикселям, что вызывает размытие и снижает производительность. Просто попробуйте это в симуляторе: у него есть возможность выделить проблемное выравнивание.
Codo
31
На самом деле, лучшая реализация (с меньшей вероятностью поломка в будущем) - это использовать CGFLOAT_MINвместо жестко запрограммированного значения. Другими словами, не делайте этого return 1.0fили 0.1fвместо этого. return CGFLOAT_MINЕсли Apple когда-либо изменит минимально допустимое значение, вам придется изменить код, если вы жестко закодируете возвращаемое значение. Кроме того, вы уже не знаете, используете ли вы наименьшее возможное значение. Используя определенную константу, вы гарантированно будете использовать наименьшее возможное значение, и ваш код переживет изменения ОС.
Крис Остмо
11
@Chris: Боюсь, вы не поняли. Я возвращаю не очень маленькое значение, а кратное размеру пикселя, чтобы рисунок оставался выровненным по пикселям (для хорошей производительности и четкости). Затем я смещаю его, используя вставку содержимого. Вряд ли это изменится в будущем, поскольку это значительное видимое расстояние, и ОС не может его игнорировать.
Codo
8
+1 Чтобы не использовать дробные значения пикселей в качестве смещений пользовательского интерфейса.
Ricardo Sanchez-Saez
52

Вот как скрыть заголовок первого раздела в UITableView (групповой стиль).

Решение Swift 3.0 и Xcode 8.0

  1. Делегат TableView должен реализовать метод heightForHeaderInSection

  2. В методе heightForHeaderInSection верните наименьшее положительное число. (не ноль!)

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    
        let headerHeight: CGFloat
    
        switch section {
        case 0:
            // hide the header
            headerHeight = CGFloat.leastNonzeroMagnitude
        default:
            headerHeight = 21
        }
    
        return headerHeight
    }
пользователь3378170
источник
6
мне помогло возвращение CGFloat.leastNonzeroMagnitude вместо 0. Спасибо!
anoo_radha
Идеальный ответ, спасибо
Пьер
Кстати, CGFLOAT_MINдля ObjC идентична CGFloat.leastNonzeroMagnitudeв Swift
DawnSong
36

Ответ был очень забавным для меня и моей команды и сработал как шарм.

  • В Интерфейсном Разработчике просто переместите табличное представление под другое представление в иерархии представлений.

ПРИЧИНА:

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

Гиоргос Ат
источник
1
У вас по-прежнему остается эффект матового стекла на панели навигации при прокрутке таблицы?
Codo
У вас будет этот эффект размытия при соответствующей настройке tableView. Вам нужно будет установить, contentInsetнапример, {0, 64, 0, 0}чтобы иметь смещение на 64 пикселя сверху (строка состояния плюс панель навигации). TableView должен быть прикреплен в верхней части экрана, а не topLayoutGuide (чтобы он доходил до панели навигации)
Джулиан Ф. Вайнерт,
Если вы не используете pull для обновления, это будет выглядеть нормально.
Майкл
2
Вот это да. Это сработало для меня в iOS 9 и просто поразило меня.
выделить
Это должен быть принятый ответ. Какой странный баг!
Одед Харт,
25

Используйте этот трюк для tableView сгруппированного типа

Скопируйте и вставьте ниже код для представления таблицы в методе viewDidLoad :

tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tableView.bounds.size.width, 0.01f)];
Нитеш Борад
источник
Я не пробовал, но подозреваю, что это решение имеет тот же недостаток, что и некоторые другие предлагаемые решения: рисунки больше не выравниваются по пикселям, что вызывает размытие и снижает производительность. Симулятор может это выявить: у него есть возможность выделить проблемное выравнивание. Однако если округлить до 0, то это действительно хорошее решение.
Codo
Да, думаю, оно округляется до 0. Потому что я использовал его много раз, но не обнаружил размытия на рисунках.
Нитеш Борад,
TableHeaderView и вид заголовка раздела? в чем разница,
AsifHabib
Или немного короче: _tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)].
Mojuba
@AsifHabib: tableHeaderView размещается вверху всех элементов таблицы. Это заголовок для самой таблицы. И вид заголовка раздела - это вид, который нужно разместить в каждом разделе. В соответствии с указанным количеством разделов в таблице может быть много видов заголовков разделов. Но будет только одно представление заголовка таблицы.
Нитеш Борад,
21

это нормально.

override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if section == 0 {
        return CGFloat.min
    }
    return 25
}

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    if section == 0 {
        return nil
    }else {
        ...
    }
}
TonnyTao
источник
2
Это хороший вариант моего решения, за исключением того, что в нем используются дробные значения. Таким образом, текст и изображения больше не выравниваются по пикселям, рисование замедляется, а результат может стать размытым. В симуляторе есть опция «Цвет несогласованных изображений», чтобы выявить эту проблему.
Codo
Прекрасно работает для людей вроде меня, использующих статические ячейки с containerView
тибо Ноа
3
Swift 3> 'CGFloat.min' был переименован в 'CGFloat.leastNormalMagnitude'
rjobidon
6

Я просто скопировал ваш код и попробовал. Работает нормально (пробовал в симуляторе). Прикрепил просмотр результатов. Вам ведь нужен такой взгляд? Или я неправильно понял вашу проблему?

введите описание изображения здесь

крик
источник
1
Да, это в основном то, что я хочу, за исключением того, что мое табличное представление находится в контроллере навигации. Может ли это иметь значение?
Codo
2
Я добавил tableView в контроллер навигации, и ваша ситуация появилась :) Я думаю, что в iOS 7 эта высота заголовка исправлена ​​по умолчанию в виде таблицы сгруппированных стилей. Изменяя фрейм tableView, первое представление заголовка может быть скрыто (например, set x = 0 y = -40). Однако я знаю, что это решение не лучшее решение.
caglar
1
Большое спасибо за вашу работу. Таким образом, кажется, что проблема возникает только в том случае, если табличное представление использует сгруппированный стиль и содержится в контроллере навигации.
Codo,
Пытаясь перейти с viewcontroller на tableviewcontroller, я не смог исправить проблему с заголовком. Возможно, я что-то упускаю, пытаясь преобразовать. (iOS 7.0.3 sim)
Евгений Петров
1
Эта проблема также присутствует на этом снимке! 0-я ячейка не начинается с x: 0.0f и y: 0.0f.
Burhanuddin Sunelwala
6

Swift3: heightForHeaderInSection работает с 0, вам просто нужно убедиться, что заголовок установлен на clipsToBounds.

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
       return 0
}

если вы не установите clipsToBounds, скрытый заголовок будет виден при прокрутке.

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    guard let header = view as? UITableViewHeaderFooterView else { return }

    header.clipsToBounds = true
}
h.martin
источник
1
clipsToBound = true очень важно, если вы планируете полностью скрыть вид заголовка раздела. Установить его высоту на 0 / CGFLOAT_MIN недостаточно.
Altimac
5

Обновление [19.09.17]: старый ответ больше не работает для меня в iOS 11. Спасибо, Apple. Следующие сделали:

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionHeaderHeight = 20.0f;
self.tableView.contentInset = UIEdgeInsetsMake(-18.0, 0.0f, 0.0f, 0.0);

Предыдущий ответ:

Как указано в комментариях Криса Остомо, у меня сработало следующее:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return CGFLOAT_MIN; // to get rid of empty section header
}
Маниндра Мохарана
источник
Я подозреваю, что содержимое вашего табличного представления больше не выровнено по пикселям, что вызывает размытие и снижает производительность. Симулятор может это выявить: у него есть возможность выделить проблемное выравнивание. Однако если округлить до 0, то это действительно хорошее решение.
Codo
Нет, я не заметил никаких проблем с контентом. Ограничения казались прекрасными.
Маниндра Мохарана,
1
Хорошо! Больше не работает в iOS 11! Мое исправление длилось меньше недели .. 😞
Маниндра Мохарана
4

Вот как избавиться от заголовка верхнего раздела в сгруппированном UITableView в Swift:

tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
Харрис
источник
3

В Swift 4.2 и многих более ранних версиях вместо установки высоты первого заголовка равной 0, как в других ответах, вы можете просто установить для других заголовков значение nil. Допустим, у вас есть два раздела, и вы хотите, чтобы только второй (т.е. 1) имел заголовок. В этом заголовке будет текст Foobar :

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return section == 1 ? "Foobar" : nil
}
Гудолл
источник
3

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

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

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}
Авинаш
источник
Это мне как раз и нужно. Простое и легкое решение. 1+
iGhost
0

Я пока не могу комментировать, но подумал, что добавлю, что если у вас есть UISearchControllerна вашем контроллере UISearchBarкак ваш tableHeaderView, установив высоту первой секции как 0 вheightForHeaderInSection действительно работает.

я использую self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height); тем, что по умолчанию панель поиска скрыта.

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

Раэсу
источник
0

проще всего вернуться nilили перейти ""в func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?раздел, в котором вы не хотите отображать заголовок.

Вилем Курц
источник
0

Версия Swift: Swift 5.1
В основном вы можете установить высоту в делегате tableView следующим образом:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
   return UIView(frame: CGRect(x: 0, y: 0, width: view.width, height: CGFloat.leastNormalMagnitude))
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
   return CGFloat.leastNormalMagnitude
}

Иногда, когда вы создавали UITableView с помощью Xib или Storyboard, ответ up не работает. вы можете попробовать второе решение:

let headerView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
self.tableView.tableHeaderView = headerView

Надеюсь, это сработает для вас!

Mistdon
источник
0

Следующее работало для меня с iOS 13.6 и Xcode 11.6 с a, UITableViewControllerкоторый был встроен в UINavigationController:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    nil
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    .zero
}

Никаких других уловок не требуется. Эти overrideключевые слова не нужны , если не используется UITableViewController(то есть , когда только были реализованы UITableViewDelegateметоды). Конечно, если бы целью было скрыть только заголовок первого раздела, тогда эту логику можно было бы обернуть в условное выражение как таковое:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    if section == 0 {
        return nil
    } else {
        // Return some other view...
    }
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if section == 0 {
        return .zero
    } else {
        // Return some other height...
    }
}
rlziii
источник