Ubah Perilaku Pengguliran Default dari Header Bagian UITableView


147

Saya memiliki UITableView dengan dua bagian. Ini adalah tampilan tabel sederhana. Saya menggunakan viewForHeaderInSection untuk membuat tampilan kustom untuk header ini. Sejauh ini baik.

Perilaku pengguliran default adalah bahwa ketika suatu bagian ditemui, header bagian tetap berlabuh di bawah bilah Nav, hingga bagian berikutnya bergulir ke tampilan.

Pertanyaan saya adalah ini: dapatkah saya mengubah perilaku default sehingga header bagian TIDAK tetap berlabuh di atas, melainkan, gulir di bawah bilah nav dengan sisa baris bagian?

Apakah saya kehilangan sesuatu yang jelas?

Terima kasih.


1
Itu pasti salah satu pertanyaan tertulis terbaik di situs ini! :) Terima kasih.
Fattie

1
Periksa di sini untuk cara yang tepat untuk mencapai efek ini stackoverflow.com/a/13735238/1880899
Sumit Anantwar

Jawaban:


175

Cara saya memecahkan masalah ini adalah dengan menyesuaikan contentOffsetsesuai dengan contentInsetdi UITableViewControllerDelegate(meluas UIScrollViewDelegate) seperti ini:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
       CGFloat sectionHeaderHeight = 40;
   if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
       scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
   } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
       scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
   }
}

Satu-satunya masalah di sini adalah ia kehilangan sedikit pantulan ketika menggulir kembali ke atas.


{CATATAN: "40" harus sama persis dengan header bagian 0 ANDA. Jika Anda menggunakan angka yang lebih besar dari tinggi bagian 0 header Anda, Anda akan melihat bahwa rasa-jari terpengaruh (coba seperti "1000" dan Anda akan melihat perilaku bouncing agak aneh di atas). jika nomornya cocok dengan tinggi bagian 0 header Anda, nuansa jari tampaknya sempurna atau hampir sempurna.}


1
Solusi sempurna daripada yang di atas.
prathumca

4
Terima kasih! Ini adalah solusi sempurna. Apakah Anda punya solusi untuk bagian footer?
Tuan Nguyen

12
Solusi ini tidak menangani tap-on-menubar dengan benar, yang seharusnya bergulir ke bagian atas daftar.
Reid Ellis

jika Anda memerlukan perilaku yang sama untuk tampilan footer bagian, ubah saja baris terakhir seperti ini: scrollView.contentInset = UIEdgeInsetsMake (0, 0, sectionHeaderHeight, 0)
alex

Ini tampaknya sudah cukup: scrollView.contentInset = UIEdgeInsetsMake (scrollView.contentOffset.y> = 0? -ScrollView.contentOcsetent.y: 0, 0, 0, 0);
MacMark

85

Anda juga dapat menambahkan bagian dengan nol baris di bagian atas dan cukup menggunakan footer dari bagian sebelumnya sebagai header untuk yang berikutnya.


13
Dalam kasus saya di mana saya memiliki lebih dari 2 bagian, catatan kaki akan berlabuh di bagian bawah ..
Joseph Lin

3
Ini kreatif tetapi Anda perlu menyesuaikan indexPath jika Anda menggunakan NSFetchedResultsController untuk memuat tabel.
XJones

+1 sejauh ini solusi TERBAIK - butuh saya seperti 3 baris untuk diterapkan!
Jon

Brilliant Brilliant Brilliant :-)
iphonic

Bagaimana ini bekerja untuk footer yang berlabuh? Sangat menghargai bantuan! Terima kasih
darwindeeds

36

Jika saya melakukan ini, saya akan mengambil keuntungan dari fakta bahwa UITableViews dalam gaya Polos memiliki header yang lengket dan yang dalam gaya Grouped tidak. Saya mungkin paling tidak akan mencoba menggunakan sel tabel kustom untuk meniru tampilan sel Plain di tabel yang dikelompokkan.

Saya belum benar-benar mencoba ini sehingga mungkin tidak berhasil, tapi itulah yang saya sarankan lakukan.


Mungkin akan berhasil, tetapi apakah sudah dicoba? Dan sepertinya banyak pekerjaan ketika jawaban @ voidStern bekerja dengan sempurna !!
bentford

Jawaban voidStern tidak bekerja untuk saya ketika saya memiliki lebih dari dua bagian. Jawaban Colin lebih sederhana / lebih elegan, tanpa perlu mengubah nomor bagian secara manual dan menambah jumlah bagian.
Joseph Lin

Tips: gunakan tableView.separatorColor = [UIColor clearColor];untuk meniru tampilan tabel biasa.
Joseph Lin

3
Saya mencoba melakukan ini, tetapi ketika saya tidak bisa membuat sel tabel yang dikelompokkan terlihat seperti yang biasa, yaitu menghapus margin kiri dan kanan di kedua sisi sel. Bagaimana kamu melakukan ini?
Adam Carter

1
Terima kasih banyak untuk membuat hal-hal yang jelas tentang UITableViewStyle yaitu dikelompokkan dan polos, yang memutuskan apakah bagian header / footer tableview akan lengket atau tidak. Terima kasih banyak @Colin Barrett
Dhaval H. Nena

28

Saya tahu ini datang terlambat, tetapi saya telah menemukan solusi definitif!

Apa yang ingin Anda lakukan adalah jika Anda memiliki 10 bagian, biarkan dataSource kembali 20. Gunakan angka genap untuk header bagian, dan angka ganjil untuk konten bagian. sesuatu seperti ini

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section%2 == 0) {
        return 0;
    }else {
        return 5;
    }
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if (section%2 == 0) {
        return [NSString stringWithFormat:@"%i", section+1];
    }else {
        return nil;
    }
}

Voa! : D


ide yang hebat. tetapi jika Anda memiliki judul indeks bagian, saya menduga ini akan mengacaukannya.
roocell

Mengapa? Anda dapat melakukan hal yang sama dengan judul bagian. Ingat saja nol untuk angka ganjil dan judul untuk angka genap.
LocoMike

1
ya - metode ini sangat bagus. Itu banyak pembukuan (mungkin harus dilakukan dengan cara saya harus mendapatkan judul bagian) Tapi itu berhasil. Triknya adalah numberOfRowsInSection dan cellForRowAtIndexPath menggunakan if (bagian% 2! = 0 && bagian! = 0) sedangkan titleForHeaderInSection dan fungsi indeks bagian lain digunakan jika (bagian% 2 == 0)
roocell

pencetus harus memilih ini sebagai jawabannya. Akan lebih bagus jika ada cara untuk subclass uitableview untuk memasang judul bagian secara otomatis.
roocell

Ini yang terbaik bagi saya. Saya mencoba solusi @ Colin terlebih dahulu, tetapi tidak berhasil dengan sangat disesuaikan UITableViewyang saya gunakan.
kubi

15

Ada beberapa hal yang perlu dilakukan untuk menyelesaikan masalah ini secara non-hacky:

  1. Setel gaya tampilan tabel ke UITableViewStyleGrouped
  2. Atur tampilan tabel backgroundColormenjadi[UIColor clearColor]
  3. Setel backgroundViewpada setiap sel tampilan tabel ke tampilan kosong denganbackgroundColor [UIColor clearColor]
  4. Jika perlu, atur tampilan tabel dengan rowHeighttepat, atau ganti tableView:heightForRowAtIndexPath:jika masing-masing baris memiliki ketinggian yang berbeda.

(+1) @Neil, saya mencoba jawaban Anda tetapi sayangnya, karena UITableViewStyleGroupedsel tabel memiliki margin tambahan yang mengubah perataannya dengan header. Ini adalah masalah ketika Anda benar-benar ingin menggambarkan tabel multi-kolom dan menggunakan header untuk menampilkan judul kolom (dan kemudian membuat entri tabel individu sejajar dengan judul-judul ini).
brainjam

15

Awalnya diposting di sini , solusi cepat menggunakan IB. Hal yang sama dapat dilakukan secara terprogram meskipun cukup sederhana.

Cara yang mungkin lebih mudah untuk mencapai ini (menggunakan IB):

Seret UIView ke TableView Anda untuk menjadikannya tampilan tajuk.

  1. Atur tinggi tampilan tajuk menjadi 100px
  2. Setel contentview setInset (atas) ke -100
  3. Header bagian sekarang akan bergulir seperti sel biasa.

Beberapa orang berkomentar mengatakan bahwa solusi ini menyembunyikan header pertama, namun saya belum melihat adanya masalah seperti itu. Ini bekerja dengan sempurna untuk saya dan sejauh ini merupakan solusi paling sederhana yang pernah saya lihat sejauh ini.


Perhatikan bahwa Anda mungkin harus mengatur tampilan untuk menggunakan warna latar belakang clearcolor, jika tidak, jika Anda menggulir melewati bagian atas yang Anda lihat putih di bouncing.
Doc

3
Itu menyembunyikan sundulan pertama saya
Leena

Leena, versi iOS apa yang Anda jalankan? Apakah tampilan UITableViewController, atau UIView dengan UITableView di dalamnya? Saya tidak yakin mengapa bagi sebagian orang solusi ini menyembunyikan header pertama jadi saya mencoba untuk menemukan perbedaan.
Doc

Solusi ini sempurna. Saya mencari tampilan latar belakang sel atas dan bawah tanpa batas - ini benar-benar berhasil. Bagus!
Taylor Halliday

Solusi ini sangat bagus. Lebih mudah dicapai daripada jawaban lain di utas ini. Menurut pendapat saya, ini harus menjadi jawaban yang diterima.
John Rogers

15

Saya tidak senang dengan solusi yang dijelaskan di sini sejauh ini, jadi saya mencoba menggabungkannya. Hasilnya adalah kode berikut, terinspirasi oleh @awulf dan @cescofry. Ini bekerja untuk saya karena saya tidak memiliki header tampilan tabel nyata. Jika Anda sudah memiliki header tampilan tabel, Anda mungkin harus menyesuaikan ketinggian.

// Set the edge inset
self.tableView.contentInset = UIEdgeInsetsMake(-23.0f, 0, 0, 0);

// Add a transparent UIView with the height of the section header (ARC enabled)
[self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 23.0f)]];

Ini adalah solusi paling sederhana yang saya temukan.
Zorayr

Ini bekerja untuk saya di iOS9.2, jadi meskipun jawaban yang lebih lama, itu masih berlaku. Dan itu tidak menyembunyikan tajuk bagian pertama. Bekerja, dan bekerja dengan sempurna.
idStar

Sempurna. Jika tampilan tabel Anda sudah memiliki tajuk, tingkatkan ketinggiannya dengan offset kemudian tambah konstanta kendala konten tajuk untuk menggeser konten ke bawah ke posisi semula
Jason

14

Cukup ubah Gaya TableView:

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

Dokumentasi UITableViewStyle :

UITableViewStylePlain- Tampilan tabel biasa. Setiap header atau footer bagian ditampilkan sebagai pemisah inline dan mengapung ketika tampilan tabel digulir.

UITableViewStyleGrouped- Tampilan tabel yang bagian-bagiannya menampilkan kelompok baris yang berbeda. Header dan footer bagian tidak mengapung.


jawaban yang bagus, bekerja untuk saya. tidak perlu bekerja
Shams Ahmed

9

Pilih gaya TableView yang Dikelompokkan

Pilih gaya Tampilan Tabel Dikelompokkan dari tableView's Attribute Inspector Anda di storyboard.


5

Atur tajuk Lihat tabel dengan tampilan transparan dengan ketinggian tajuk yang sama di tampilan bagian. Juga memulai tampilan tabel dengan bingkai di -tinggi.

self.tableview = [[UITableView alloc] initWithFrame:CGRectMake(0, - height, 300, 400)];

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)] autorelease];
[self.tableView setTableHeaderView:headerView];

4

Saya menemukan solusi alternatif, gunakan sel pertama dari setiap bagian, bukan bagian header nyata, solusi ini tidak tampak begitu bersih, tetapi berfungsi dengan sangat baik, Anda dapat menggunakan sel prototipe yang ditentukan untuk bagian header Anda, dan dalam metode cellForRowAtIndexPath minta indexPath.row == 0, jika benar, gunakan sel prototipe bagian header, kalau tidak gunakan sel prototipe default Anda.


Jika Anda masih ingin bekerja dengan indexPath.row& indexPath.section, pastikan Anda mengembalikan tinggi 0.0funtuk - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)sectionsehingga header Anda tidak terlihat.
Sup

4

Ubah Gaya TableView Anda:

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

Sesuai dokumentasi apel untuk UITableView:

UITableViewStylePlain- Tampilan tabel biasa. Setiap header atau footer bagian ditampilkan sebagai pemisah inline dan mengapung ketika tampilan tabel digulir.

UITableViewStyleGrouped- Tampilan tabel yang bagian-bagiannya menampilkan kelompok baris yang berbeda. Header dan footer bagian tidak mengapung. Semoga perubahan kecil ini akan membantu Anda ..


2

Sekarang gaya yang dikelompokkan pada dasarnya terlihat sama dengan gaya biasa di iOS 7 (dalam hal kerataan dan latar belakang), bagi kami perbaikan terbaik dan termudah (yaitu paling tidak hacky) adalah dengan hanya mengubah gaya tampilan tabel menjadi dikelompokkan. Jacking dengan contentInsets selalu menjadi masalah ketika kami mengintegrasikan bilah nav scroll-away di bagian atas. Dengan gaya tampilan tabel yang dikelompokkan, tampilannya persis sama (dengan sel kami) dan header bagian tetap diperbaiki. Tidak ada keanehan yang bergulir.


Ini adalah solusi terbaik terutama jika sel-sel tersuai, sepertinya hanya menghentikan "tahan" dari header bagian ketika gulir menyentuh bagian atas.
Baja Daur Ulang

1

Tetapkan inset negatif ke tableView Anda. Jika Anda memiliki header bagian tinggi 22px, dan Anda tidak ingin itu menjadi lengket, segera setelah Anda memuat ulang Data, tambahkan:

self.tableView.contentInset = UIEdgeInsetsMake(-22, 0, 0, 0); 
self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height+22); 

Bekerja seperti pesona bagi saya. Juga berfungsi untuk bagian footer, cukup tetapkan inset negatif di bagian bawah.


Ini hanya memotong header pertama ??
cannyboy

Bekerja dengan baik untuk saya !! Terima kasih
Daniel

0

Saya menambahkan tabel ke Tampilan Gulir dan tampaknya berfungsi dengan baik.


0

Periksa jawaban saya di sini . Ini adalah cara termudah untuk mengimplementasikan tajuk bagian yang tidak mengambang tanpa peretasan.


0

Jawaban @ LocoMike paling cocok dengan tableView saya, namun itu rusak ketika menggunakan footer juga. Jadi, ini adalah solusi yang diperbaiki ketika menggunakan header dan footer:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return (self.sections.count + 1) * 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section % 3 != 1) {
        return 0;
    }
    section = section / 3;
    ...
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return nil;
    }
    section = section / 3;
    ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return 0;
    }
    section = section / 3;
    ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return 0;
    }
    section = section / 3;
    ...
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return nil;
    }
    section = section / 3;
    ...
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return nil;
    }
    section = section / 3;
    ...
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int section = indexPath.section;
    section = section / 3;
    ...
}

0

Versi cepat jawaban @awulf, yang sangat bagus!

func scrollViewDidScroll(scrollView: UIScrollView) {
    let sectionHeight: CGFloat = 80
    if scrollView.contentOffset.y <= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake( -scrollView.contentOffset.y, 0, 0, 0)
    }else if scrollView.contentOffset.y >= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake(-sectionHeight, 0, 0, 0)
    }
}

-2

Saya telah belajar bahwa hanya menyetel properti tableHeaderView melakukannya, yaitu:

 tableView.tableHeaderView = customView;

dan hanya itu.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.