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.

davidjhinson
sumber
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.}

awulf
sumber
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.

membatalkanStern
sumber
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.

Colin Barrett
sumber
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

LocoMike
sumber
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.
Neil Gall
sumber
(+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.

Dokter
sumber
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)]];
Thomas Kekeisen
sumber
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.

Arthur S
sumber
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.

Arjun Shukla
sumber
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];
kue cescofry
sumber
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.

AlexBB
sumber
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 ..

Aks
sumber
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.

Greg Combs
sumber
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.

Mike A
sumber
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.

Dolbex
sumber
0

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

Sumit Anantwar
sumber
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;
    ...
}
marmor
sumber
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)
    }
}
Jeff
sumber
-2

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

 tableView.tableHeaderView = customView;

dan hanya itu.

Soni
sumber