Як приховати заголовок першого розділу в 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, що призводить до дещо товстішої лінії нижче панелі навігації. Однак я вдячний, якщо хтось знає, як заголовок першого розділу можна повністю приховати.

Оновлення

Відповідно до аналізу caglar ( https://stackoverflow.com/a/19056823/413337 ), проблема виникає лише в тому випадку, якщо подання таблиці міститься в навігаційному контролері.


Я не отримав цю частину => if (section == 0) view view; повернути нуль; тобто повернення виду, коли його перший розділ і нульове інакше?
— Дзен

Ідея полягає в тому, щоб повернути вигляд з висотою 0 для першого розділу і повернути нуль для всіх інших розділів, щоб табличний вигляд використовував для них вид заголовка за замовчуванням. Нуль частина добре працює; у таблиці подано заголовок цих розділів. Але частина розділу 0 не має значення, оскільки метод ніколи не викликається section == 0.
— Кодо

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);
}

Швидкий:

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 ще краще для його приховування.
— Чак Крутсінгер

4
Я спробував використовувати 0,1f. Але результат полягає в тому, що малюнки більше не вирівнюються до пікселів, що спричиняє розмиття та знижує продуктивність. Просто спробуйте в тренажері: він має можливість виділити проблемне вирівнювання.
— Кодо

31
Насправді, кращою реалізацією (меншою ймовірністю в майбутньому зламатися) є використання CGFLOAT_MINзамість твердо кодованого значення. Іншими словами, не return 1.0fчи 0.1fзамість цього, return CGFLOAT_MINякщо Apple , коли - небудь зміни мінімально допустиме значення, ви будете мати код для зміни , якщо ви жорстко код, що повертається. Крім того, ви вже не знаєте, чи використовуєте ви найменше можливе значення. Використовуючи визначену константу, ви гарантовано використовуєте найменше можливе значення, і ваш код переживе зміни ОС.
— Кріс Остмо

11
@Chris: Я боюся, що ти не здогадався. Я не повертаю дуже маленьке значення, але кратне розміру пікселя, щоб малюнок залишався вирівняним пікселем (для гарної продуктивності та чіткості). Потім я компенсую це за допомогою вставки вмісту. Це навряд чи зміниться в майбутньому, оскільки це значна, видима відстань, а не те, що ОС може ігнорувати.
— Кодо

8
+1 Не використовуйте значення дробових пікселів як компенсацію інтерфейсу користувача.
— Рікардо Санчес-Саес

52

Ось як приховати заголовок першого розділу в UITableView (згрупований стиль).

Swift 3.0 та Xcode 8.0 Рішення

  1. Делегат TableView повинен реалізувати метод heightForHeaderInSection

  2. У межах висотиForHeaderInSection поверніть найменше додатне число. (не нуль!)

    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
    }
    

6
повернення CGFloat.leastNonzeroMagnitude замість 0 допомогло мені. Дякую!
— anoo_radha

Ідеальна відповідь, дякую
— П'єр

До речі, CGFLOAT_MINдля objc є ідентичним CGFloat.leastNonzeroMagnitudeу Swift
— DawnSong

36

Відповідь була дуже смішною для мене та моєї команди, і працювала як принадність

  • У програмі інтерфейсу просто перемістіть перегляд таблиці під інший вигляд в ієрархії подання.

ПРИЧИНА:

Ми помітили, що це відбувається лише для першого перегляду в Ієрархії перегляду, якщо цей перший вид є UITableView . Отже, всі інші подібні UITableView не мають цього дратівливого розділу, крім першого. Ми намагалися перемістити UITableView з першого місця в ієрархії перегляду, і все працювало так, як очікувалося.


1
У вас все ще виникає ефект матового скла на панелі навігації, коли ви прокручуєте подання таблиці?
— Кодо

Цей ефект розмивання ви матимете, коли відповідно встановите таблицю ViewView. Вам потрібно встановити значення, contentInsetнаприклад, {0, 64, 0, 0}щоб зміщення 64 пікселів у верхній частині (рядок стану плюс панель навігації). Таблицю TableView потрібно прикріпити у верхній частині екрана, а не на topLayoutGuide (щоб вона досягла під навігаційною панеллю)
— Julian F. Weinert

Якщо ви не використовуєте функцію "pull" для оновлення, це виглядатиме добре.
— Майкл

2
Ого. Це працювало для мене в iOS 9 і просто підірвало мою думку.
— виділити

Це має бути прийнятою відповіддю. Такий дивний клоп!
— Одед Харт

25

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

Скопіюйте пасту нижче коду для перегляду таблиці у методі viewDidLoad :

tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tableView.bounds.size.width, 0.01f)];

Я не пробував цього, але підозрюю, що це рішення має такий же недолік, як і деякі інші запропоновані рішення: малюнки більше не вирівнюються до пікселів, що спричиняє розмиття та знижує продуктивність. Симулятор може розкрити це: він має можливість виділити проблемне вирівнювання. Однак, якщо все-таки це округлення до 0, то справді це приємне рішення.
— Кодо

Так, я думаю, що це округлює до 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 {
        ...
    }
}

2
Це хороший варіант мого рішення, за винятком того, що він використовує дробові значення. Таким чином, текст і зображення більше не вирівнюються до пікселів, малювання сповільнюється, і результат може стати розмитим. Симулятор має опцію "Кольорові несогласовані зображення" для виявлення цієї проблеми.
— Кодо

Працює чудово для таких людей, як я, використовуючи статичні комірки з контейнером
— View

3
Swift 3> "CGFloat.min" перейменовано на "CGFloat.leastNormalMagnitude"
— rjobidon

6

Я просто скопіював ваш код і спробував. Він працює нормально (спробував у тренажері). Я додав перегляд результатів. Ви хочете такого виду, правда? Або я неправильно зрозумів вашу проблему?

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


1
Так, це в основному те, що я хочу, за винятком мого подання таблиці в контролері навігації. Чи може це змінити значення?
— Кодо

2
Я додав tableView до контролера навігації, і ваша ситуація з'являється :) Я думаю, що в iOS 7 цю висоту заголовка виправте за замовчуванням у згрупованому стилі таблиці таблиць. Змінюючи кадр tableView, вигляд першого заголовка може бути прихованим. (Наприклад, встановити x = 0 y = -40). Однак я знаю, що це рішення не є хорошим рішенням.
— caglar

1
Дуже дякую за вашу роботу. Отже, здається, що проблема виникає лише в тому випадку, коли у таблиці подання використовується згрупований стиль та міститься в контролері навігації.
— Кодо

Намагаючись перейти з 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
}

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, то справді це приємне рішення.
— Кодо

Ні, я не помітив жодних проблем із вмістом. Обмеження здалося прекрасним.
— Маніндра Мохарана

1
Welp! Більше не працює в 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
Здебільшого ви можете встановити висоту в delegate 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, відповідь вгору не працює. ви можете спробувати друге рішення:

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

Сподіваюся, це працює для вас!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.