Cara menyembunyikan header bagian pertama di UITableView (gaya berkelompok)

108

Karena desain tampilan tabel menggunakan gaya yang dikelompokkan berubah drastis dengan iOS 7, saya ingin menyembunyikan (atau menghapus) tajuk bagian pertama. Sejauh ini saya belum berhasil mencapainya.

Agak disederhanakan, kode saya terlihat seperti ini:

- (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 ...
    }
}

Jika saya mengembalikan tinggi 0, dua metode lainnya tidak akan pernah dipanggil dengan indeks bagian 0. Namun header bagian kosong masih digambar dengan tinggi default. (Di iOS 6, kedua metode ini dipanggil. Namun, hasil yang terlihat sama.)

Jika saya mengembalikan nilai yang berbeda, header bagian mendapatkan ketinggian yang ditentukan.

Jika saya mengembalikan 0,01, itu hampir benar. Namun, saat saya mengaktifkan "Warna Gambar Tidak Sejajar" di simulator, ini menandai semua sel tampilan tabel (yang tampaknya merupakan konsekuensi logis).

Jawaban atas pertanyaan UITableView: hide header from empty section sepertinya menunjukkan bahwa beberapa orang berhasil menyembunyikan header bagian tersebut. Tapi itu mungkin berlaku untuk gaya polos (bukan yang dikelompokkan).

Kompromi terbaik sejauh ini adalah mengembalikan tinggi 0,5, menghasilkan garis yang agak lebih tebal di bawah bilah navigasi. Namun, saya akan menghargai jika ada yang tahu bagaimana header bagian pertama dapat disembunyikan sepenuhnya.

Memperbarui

Menurut analisis caglar ( https://stackoverflow.com/a/19056823/413337 ), masalah hanya muncul jika tampilan tabel terdapat dalam pengontrol navigasi.

Codo
sumber
Saya tidak mendapatkan bagian itu => if (section == 0) return view; kembali nihil; yaitu mengembalikan tampilan saat bagian pertama dan nihil sebaliknya?
Zen
Idenya adalah mengembalikan tampilan dengan tinggi 0 untuk bagian pertama dan mengembalikan nihil untuk semua bagian lainnya sehingga tampilan tabel menggunakan tampilan header default untuk mereka. Bagian nol bekerja dengan baik; tampilan tabel menunjukkan header untuk bagian ini. Tetapi bagian untuk bagian 0 tidak relevan karena metode ini tidak pernah dipanggil dengan section == 0.
Codo
1
Jawaban ini sepertinya singkat dan manis. stackoverflow.com/a/23955420/3965
Tuan Rogers

Jawaban:

154

Saya memiliki solusi yang tampaknya cukup bersih bagi saya. Jadi saya menjawab pertanyaan saya sendiri.

Karena 0 sebagai tinggi header bagian pertama tidak berfungsi, saya mengembalikan 1. Kemudian saya menggunakan contentInset untuk menyembunyikan ketinggian itu di bawah bilah navigasi.

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

Cepat:

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)
}
Codo
sumber
6
Menggunakan tinggi header 0.1f bahkan lebih baik untuk menyembunyikannya.
Chuck Krutsinger
4
Saya sudah mencoba menggunakan 0.1f. Namun akibatnya gambar tidak lagi sejajar dengan piksel, menyebabkan kabur dan mengurangi performa. Coba saja di simulator: ini memiliki opsi untuk menyorot keselarasan bermasalah.
Codo
31
Sebenarnya, implementasi yang lebih baik (kemungkinan tidak akan rusak di masa mendatang) adalah dengan menggunakan CGFLOAT_MINnilai hard-code. Dengan kata lain, jangan return 1.0fatau 0.1fsebaliknya, return CGFLOAT_MINJika Apple pernah mengubah nilai minimum yang dapat diterima, Anda akan memiliki kode untuk diubah jika Anda melakukan hard-code pada nilai pengembalian. Selain itu, Anda sudah tidak tahu apakah Anda menggunakan nilai sekecil mungkin. Dengan menggunakan konstanta yang ditentukan, Anda dijamin akan menggunakan nilai sekecil mungkin dan kode Anda akan bertahan dari perubahan OS.
Chris Ostmo
11
@ Chris: Saya khawatir Anda tidak mengerti. Saya tidak mengembalikan nilai yang sangat kecil tetapi kelipatan dari ukuran piksel sehingga gambar tetap selaras dengan piksel (untuk kinerja dan kerenyahan yang baik). Saya kemudian mengimbanginya menggunakan inset konten. Ini tidak mungkin berubah di masa depan karena ini adalah jarak yang cukup besar dan terlihat dan bukan sesuatu yang dapat diabaikan oleh OS.
Codo
8
+1 Untuk tidak menggunakan nilai piksel pecahan sebagai offset UI.
Ricardo Sanchez-Saez
52

Ini adalah cara menyembunyikan header bagian pertama di UITableView (gaya yang dikelompokkan).

Solusi Swift 3.0 & Xcode 8.0

  1. Delegasi TableView harus mengimplementasikan metode heightForHeaderInSection

  2. Dalam metode heightForHeaderInSection, kembalikan bilangan positif terkecil. (bukan nol!)

    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
    }
pengguna3378170
sumber
6
mengembalikan CGFloat.leastNonzeroMagnitude alih-alih 0 membantu saya. Terima kasih!
anoo_radha
Jawaban sempurna, Terima kasih
Pierre
Omong-omong, CGFLOAT_MINuntuk objc identik dengan CGFloat.leastNonzeroMagnitudedi Swift
DawnSong
36

Jawabannya sangat lucu bagi saya dan tim saya, dan bekerja dengan sangat baik

  • Di Pembuat Antarmuka, Cukup pindahkan tampilan tabel di bawah tampilan lain dalam hierarki tampilan.

ALASAN:

Kami mengamati bahwa ini hanya terjadi untuk Tampilan Pertama dalam Hierarki Tampilan, jika tampilan pertama ini adalah UITableView . Jadi, semua UITableView serupa lainnya tidak memiliki bagian yang mengganggu ini, kecuali yang pertama. Kami Mencoba memindahkan UITableView dari tempat pertama dalam hierarki tampilan, dan semuanya berfungsi seperti yang diharapkan.

Giorgos Ath
sumber
1
Apakah Anda masih memiliki efek kaca buram dari bilah navigasi saat menggulir tampilan tabel?
Codo
Anda akan mendapatkan efek blur ini ketika Anda mengatur tableView Anda. Anda perlu mengatur contentInsetke misalnya {0, 64, 0, 0}untuk memiliki 64px offset dari atas (status bar plus bar navigasi). TableView perlu dilampirkan di bagian atas layar, bukan topLayoutGuide (agar dapat menjangkau di bawah bilah navigasi)
Julian F. Weinert
Jika Anda tidak menggunakan tarik untuk menyegarkan ini akan terlihat baik-baik saja.
Michael
2
Wow. Ini bekerja untuk saya di iOS 9 dan hanya mengejutkan saya.
alokasikan
Ini harus menjadi jawaban yang diterima. Bug yang aneh!
Oded Harth
25

Gunakan trik ini untuk tipe tableView yang dikelompokkan

Salin tempel kode di bawah ini untuk tampilan tabel Anda dalam metode viewDidLoad :

tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tableView.bounds.size.width, 0.01f)];
Nitesh Borad
sumber
Saya belum mencobanya tetapi saya curiga solusi ini memiliki kerugian yang sama dengan beberapa solusi lain yang diusulkan: gambar tidak lagi selaras dengan piksel, menyebabkan kabur dan mengurangi kinerja. Simulator dapat mengungkapkannya: ia memiliki opsi untuk menyoroti kesejajaran yang bermasalah. Namun, jika dibulatkan menjadi 0, maka itu memang solusi yang bagus.
Codo
Ya, saya kira itu membulatkan menjadi 0. Karena saya menggunakannya berkali-kali, tetapi tidak menemukan gambar buram.
Nitesh Borad
Tampilan TableHeaderView dan Bagian Header? apa bedanya,
AsifHabib
Atau sedikit lebih pendek: _tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)].
mojuba
@AsifHabib: tableHeaderView ditempatkan di atas semua elemen tabel. Ini adalah tampilan header untuk tabel itu sendiri. Dan tampilan header bagian adalah tampilan yang akan ditempatkan pada setiap bagian. Ada banyak tampilan tajuk bagian sesuai dengan tidak ada bagian yang ditentukan dalam tabel. Namun, hanya akan ada satu tampilan header tabel.
Nitesh Borad
21

cara ini tidak apa-apa.

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
sumber
2
Ini adalah variasi yang bagus dari solusi saya kecuali menggunakan nilai pecahan. Dengan begitu, teks dan gambar tidak lagi sejajar dengan piksel, gambar diperlambat dan hasilnya bisa menjadi kabur. Simulator memiliki opsi "Warna gambar tidak selaras" untuk mengungkap masalah ini.
Codo
Bekerja dengan baik untuk orang-orang seperti saya menggunakan sel statis dengan containerView
thibaut noah
3
Swift 3> 'CGFloat.min' telah diubah namanya menjadi 'CGFloat.leastNormalMagnitude'
rjobidon
6

Saya baru saja menyalin kode Anda dan mencoba. Ini berjalan normal (dicoba di simulator). Saya melampirkan tampilan hasil. Anda ingin pemandangan seperti itu, bukan? Atau saya salah paham dengan masalah Anda?

masukkan deskripsi gambar di sini

caglar
sumber
1
Ya, pada dasarnya itulah yang saya inginkan, kecuali tampilan tabel saya ada di pengontrol navigasi. Bisakah itu membuat perbedaan?
Codo
2
Saya menambahkan tableView ke pengontrol navigasi dan situasi Anda muncul :) Saya pikir di iOS 7, tinggi header ini diperbaiki secara default dalam tampilan tabel gaya yang dikelompokkan. Dengan mengubah frame tableView, tampilan header pertama mungkin disembunyikan. (Seperti set x = 0 y = -40). Namun, saya tahu solusi ini bukanlah solusi yang baik.
caglar
1
Terima kasih banyak atas pekerjaan Anda. Jadi tampaknya masalah hanya muncul jika tampilan tabel menggunakan gaya yang dikelompokkan dan terdapat dalam pengontrol navigasi.
Codo
Mencoba mengubah dari viewcontroller ke tableviewcontroller, saya tidak dapat memperbaiki masalah dengan header. Mungkin saya melewatkan sesuatu yang mencoba mengubahnya. (iOS 7.0.3 sim)
Evgeni Petrov
1
Masalah ini juga muncul di snapshot ini! sel ke-0 tidak dimulai dari x: 0.0f & y: 0.0f.
Burhanuddin Sunelwala
6

Swift3: heightForHeaderInSection berfungsi dengan 0, Anda hanya perlu memastikan header disetel ke clipsToBounds.

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

jika Anda tidak mengatur clipsToBounds header tersembunyi akan terlihat saat menggulir.

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

    header.clipsToBounds = true
}
h.martin
sumber
1
clipsToBound = true sangat penting jika Anda berencana untuk menyembunyikan tampilan header bagian sepenuhnya. Menyetel tingginya ke 0 / CGFLOAT_MIN saja tidak cukup.
Altimac
5

Pembaruan [9/19/17]: Jawaban lama tidak lagi berfungsi untuk saya di iOS 11. Terima kasih Apple. Berikut ini dilakukan:

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

Jawaban Sebelumnya:

Seperti yang diposting di komentar oleh Chris Ostomo , yang berikut ini berhasil untuk saya:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return CGFLOAT_MIN; // to get rid of empty section header
}
Manindra Moharana
sumber
Saya menduga bahwa konten tampilan tabel Anda tidak lagi sejajar dengan piksel, menyebabkan kabur dan mengurangi kinerja. Simulator dapat mengungkapkannya: ia memiliki opsi untuk menyoroti kesejajaran yang bermasalah. Namun, jika dibulatkan menjadi 0, maka itu memang solusi yang bagus.
Codo
Tidak, saya tidak melihat masalah konten apa pun. Kendala sepertinya baik-baik saja.
Manindra Moharana
1
Selamat! Tidak berfungsi di iOS 11 lagi! Perbaikan saya berlangsung kurang dari seminggu .. 😞
Manindra Moharana
4

Berikut adalah cara menghilangkan header bagian atas dalam UITableView yang dikelompokkan, di Swift:

tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
Harris
sumber
3

Di Swift 4.2 dan banyak versi sebelumnya, alih-alih menyetel tinggi header pertama ke 0 seperti di jawaban lain, Anda bisa menyetel header lain ke nil. Katakanlah Anda memiliki dua bagian dan hanya ingin bagian kedua (yaitu 1) memiliki tajuk. Header itu akan memiliki teks Foobar :

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return section == 1 ? "Foobar" : nil
}
JaneGoodall
sumber
3

Coba ini jika Anda ingin menghapus semua header bagian sepenuhnya

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

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}
Avinash
sumber
Itu yang saya butuhkan. Solusi sederhana dan mudah. 1+
iGhost
0

Saya belum bisa berkomentar tetapi saya pikir saya akan menambahkan bahwa jika Anda memiliki UISearchControllerpengontrol dengan UISearchBarsebagai milik Anda tableHeaderView, mengatur ketinggian bagian pertama sebagai 0 dalam heightForHeaderInSectionmemang berfungsi.

Saya menggunakan self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height);agar bilah pencarian disembunyikan secara default.

Hasilnya adalah tidak ada tajuk untuk bagian pertama, dan menggulir ke bawah akan menampilkan bilah pencarian tepat di atas baris pertama.

Raesu
sumber
0

termudah sejauh ini adalah untuk kembali nil, atau ""di func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?untuk bagian di mana Anda tidak ingin menampilkan sundulan.

Vilém Kurz
sumber
0

Versi Swift: Swift 5.1
Kebanyakan, Anda dapat mengatur ketinggian di delegasi tableView seperti ini:

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
}

Terkadang saat Anda membuat UITableView dengan Xib atau Storyboard, jawaban atas tidak berfungsi. Anda dapat mencoba solusi kedua:

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

Semoga berhasil untuk Anda!

mistdon
sumber