UITableView Bölüm Başlığının Varsayılan Kaydırma Davranışını Değiştirme


147

İki bölümlü bir UITableView var. Basit bir tablo görünümüdür. Bu başlıklar için özel görünümler oluşturmak için viewForHeaderInSection kullanıyorum. Çok uzak çok iyi.

Varsayılan kaydırma davranışı, bir bölümle karşılaşıldığında, bölüm başlığının bir sonraki bölüm görünüme geçene kadar Gezinme çubuğunun altında sabitlenmiş olmasıdır.

Sorum şu: bölüm başlıkları üstte sabit kalmaz, daha ziyade bölüm satırlarının geri kalanıyla gezinme çubuğunun altına kaydırmak için varsayılan davranışı değiştirebilir miyim?

Açık bir şey mi kaçırıyorum?

Teşekkürler.


1
Bu, bu sitedeki en iyi yazılı sorulardan biri olmalı! :) Teşekkürler.
Fattie

1
Bu efekti elde etmenin doğru yolu için buraya bakın stackoverflow.com/a/13735238/1880899
Sumit Anantwar

Yanıtlar:


175

Bu sorunu çözülmüş bir şekilde ayarlamak için olan contentOffsetuygun contentInsetolarak UITableViewControllerDelegate(genişletir UIScrollViewDelegate) örneğin:

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

Buradaki tek sorun, yukarı doğru kaydırırken biraz sıçraması kaybetmesidir.


{NOT: "40" bölüm 0 başlığınızın tam yüksekliği olmalıdır. Bölüm 0 başlık yüksekliğinizden daha büyük bir sayı kullanırsanız, parmak hissinin etkilendiğini görürsünüz ("1000" gibi deneyin ve hemen çıkma davranışının en üstte tuhaf olduğunu görürsünüz). sayı bölüm 0 başlık yüksekliğinizle eşleşiyorsa, parmak hissi mükemmel veya neredeyse mükemmel gibi görünür.}


1
Yukarıdakilerden daha mükemmel bir çözüm.
prathumca

4
Teşekkür ederim! Bu mükemmel bir çözüm. Bölüm altbilgisi için çözümünüz var mı?
Tuan Nguyen

12
Bu çözüm, listenin en üstüne kaydırılması gereken menülere dokunma çubuğunu doğru işlemez.
Reid Ellis

bölüm altbilgisi görünümü için aynı davranışa ihtiyacınız varsa sadece son satırı şu şekilde değiştirin: scrollView.contentInset = UIEdgeInsetsMake (0, 0, sectionHeaderHeight, 0)
alex

Bu yeterli gibi görünüyor: scrollView.contentInset = UIEdgeInsetsMake (scrollView.contentOffset.y> = 0? -ScrollView.contentOffset.y: 0, 0, 0, 0);
MacMark

85

Üstte sıfır satır içeren bir bölüm ekleyebilir ve bir önceki bölümün altbilgisini bir sonraki bölüm için başlık olarak kullanabilirsiniz.


13
Benim 2'den fazla bölüm var benim durumda, altbilgi alt çapa olacak ..
Joseph Lin

3
Bu yaratıcıdır, ancak tabloyu yüklemek için bir NSFetchedResultsController kullanıyorsanız indexPath'i ayarlamanız gerekir.
XJones

+1 en iyi çözüm - beni uygulamak için 3 satır gibi aldı!
Jon

Brilliant Brilliant Brilliant :-)
iphonic

Bu, çapalanan altbilgi için nasıl çalışır? Biraz yardım isterim! Teşekkürler
darwindeeds

36

Bunu ben yapsaydım, Düz stildeki UITableView'lerin yapışkan başlıklara sahip olması ve Gruplanmış stilde olanların olmaması gerçeğinden yararlanırdım. Muhtemelen en azından bir Gruplandırılmış tablodaki Düz hücrelerin görünümünü taklit etmek için özel bir tablo hücresi kullanmayı deneyin.

Bunu gerçekten denemedim, bu yüzden işe yaramayabilir, ama bunu yapmayı öneririm.


Muhtemelen işe yarar, ama denendi mi? Ve @ voidStern'in cevabı mükemmel bir şekilde çalıştığında çok iş gibi görünüyor !!
bentford

İkiden fazla bölümüm olduğunda voidStern'in yanıtı benim için çalışmıyor. Colin'in cevabı, bölüm numarasını manuel olarak değiştirmeye ve bölüm sayısı eklemeye gerek kalmadan daha basit / daha zariftir.
Joseph Lin

İpuçları: tableView.separatorColor = [UIColor clearColor];düz tablo görünümünü taklit etmek için kullanın .
Joseph Lin

3
Bunu yapmayı denedim, ancak gruplandırılmış tablo hücrelerini düz olanlara benzeyemediğimde, yani hücrelerin her iki tarafındaki sol ve sağ kenar boşluğunu kaldırın. Bunu nasıl yaptın?
Adam Carter

1
UITableViewStyle, yani gruplandırılmış ve düz hakkında netleştirdiğiniz için çok teşekkürler, bu da tableview'in bölüm üstbilgisinin / altbilgisinin yapışkan olup olmayacağına karar verir. Teşekkürler @Colin Barrett
H. Nena

28

Geç geldiğini biliyorum, ama kesin çözümü buldum!

Yapmak istediğiniz şey 10 bölümünüz varsa, dataSource'un 20 değerini döndürmesine izin verin. Bölüm başlıkları için çift sayılar ve bölüm içeriği için tek sayılar kullanın. böyle bir şey

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

Voila! : D


iyi fikir. ancak bölüm dizini başlıklarınız varsa, bunların dağıtılacağından şüpheleniyorum.
roocell

neden? aynısını bölüm başlıklarıyla da yapabilirsiniz. Sadece tek sayılar için nil ve çift sayı için bir başlık hatırlayın.
LocoMike

1
evet - bu yöntem harika çalışıyor. Defter tutma bir sürü oldu (muhtemelen bölüm başlıkları almak zorunda yolu ile ilgili) Ama işe yaradı. Hile sayıOfRowsInSection ve cellForRowAtIndexPath if kullanır (bölüm% 2! = 0 && bölüm! = 0), başlıkForHeaderInSection ve diğer bölüm dizin işlevleri şu durumlarda kullanırsa (bölüm% 2 == 0)
roocell

gönderen bunu cevap olarak seçmelidir. Bölüm başlıklarını otomatik olarak tutturmak için uitableview alt sınıfının bir yolu olsaydı harika olurdu.
roocell

Bu benim için en iyisi oldu. Önce @ Colin'nin çözümünü denedim, ancak kullandığım yoğun özelleştirilmiş ile iyi çalışmadı UITableView.
Kubi

15

Bu sorunu hack olmayan bir şekilde çözmek için yapılması gereken birkaç şey var:

  1. Tablo görünümü stilini UITableViewStyleGrouped
  2. Tablo görünümü Set backgroundColoriçin[UIColor clearColor]
  3. Set backgroundViewboş bir görünümü her Tablo görünümü hücredebackgroundColor [UIColor clearColor]
  4. Gerekirse, tablo görünümünü rowHeightuygun şekilde ayarlayın veya tableView:heightForRowAtIndexPath:satırların farklı yükseklikleri varsa geçersiz kılın .

(+1) @Neil, cevabınızı denedim ama maalesef, UITableViewStyleGroupedtablo hücrelerinin başlıkla hizalamalarını değiştiren ekstra kenar boşlukları var. Bu, gerçekten çok sütunlu bir tablo tasvir etmek ve sütun başlıklarını göstermek için üstbilgiyi kullanmak istediğinizde (ve daha sonra tek tek tablo girişlerinin bu başlıklarla hizalanmasını istediğinizde) bir sorundur.
brainjam

15

Başlangıçta İşte , IB kullanarak hızlı bir çözüm. Aynı şey oldukça basit bir şekilde programla yapılabilir.

Bunu başarmanın muhtemelen daha kolay bir yolu (IB kullanarak):

Üstbilgi görünümü yapmak için bir UIView'i TableView'inize sürükleyin.

  1. Bu başlık görüntüleme yüksekliğini 100 piksele ayarlayın
  2. Tablo görünümü içeriğini ayarlama
  3. Bölüm başlıkları artık tıpkı normal bir hücre gibi kaydırılacaktır.

Bazı insanlar bu çözümün ilk başlığı gizlediğini söylediler, ancak böyle bir sorunu fark etmedim. Benim için mükemmel çalıştı ve şimdiye kadar gördüğüm en basit çözümdü.


Görünümü muhtemelen açık renkli bir arka plan rengi kullanacak şekilde ayarlamanız gerektiğini unutmayın, aksi halde sekmede beyazı gördüğünüzde yukarı doğru ilerlerseniz.
Doc

3
İlk başlığımı gizliyor
Leena

Leena, hangi iOS sürümü kullanıyorsunuz? Görünüm bir UITableViewController mı yoksa içinde UITableView olan bir UIView mi? Neden bazı insanlar için bu çözümün ilk başlığı gizlediğinden emin değilim, bu yüzden herhangi bir tutarsızlık bulmaya çalışıyorum.
Doc

Bu çözüm mükemmel. Sonsuz bir üst ve alt hücre arka plan görünümü arıyorum - bu tamamen başarıyor. Güzel!
Taylor Halliday

Bu çözüm mükemmel. Bu konudaki diğer cevaplardan daha kolay elde edilir. Bence bu kabul edilen cevap olmalı.
John Rogers

15

Şimdiye kadar burada açıklanan çözümlerden memnun değildim, bu yüzden bunları birleştirmeye çalıştım. Sonuç, @awulf ve @cescofry'den esinlenilen aşağıdaki koddur. Benim için çalışıyor çünkü gerçek bir tablo görünümü üstbilgim yok. Zaten bir tablo görünümü başlığınız varsa, yüksekliği ayarlamanız gerekebilir.

// 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)]];

Bu bulduğum en basit çözümdü.
Zorayr

Bu benim için iOS9.2'de çalıştı, bu yüzden daha eski bir cevap olsa da hala geçerli. Ve ilk bölüm başlığını gizlemedi. Mükemmel çalışır ve çalışır.
idStar

Mükemmel. Tablo görünümünüzde zaten bir başlık varsa, yüksekliğini ofsetle artırın, ardından içeriği orijinal konuma kaydırmak için başlık içeriğinin üst sınır sabitini artırın
Jason

14

Sadece TableView Stilini değiştirin:

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

UITableViewStyle Belgeleri :

UITableViewStylePlain- Düz tablo görünümü. Tüm bölüm üstbilgileri veya altbilgileri, satır görünümü ayırıcıları olarak görüntülenir ve tablo görünümü kaydırıldığında yüzer.

UITableViewStyleGrouped- Bölümleri farklı satır grupları sunan tablo görünümü. Bölüm üstbilgileri ve altbilgileri yüzmez.


harika cevap, benim için çalıştı. etrafında herhangi bir çalışma gerek yok
Shams Ahmed

9

Gruplandırılmış TableView stilini seçin

Film şeridinde tableView'in Özellik Denetçisi'nden Gruplandırılmış Tablo Görünümü stilini seçin.


5

Sayfanın kesit görünümünde aynı yüksekliğe sahip şeffaf bir görünüme sahip tablonunView görünümünü ayarlayın. Ayrıca tablo görünümünü -height'ta ay frame ile başlatın.

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

Alternatif bir çözüm buldum, gerçek bir başlık bölümü yerine her bölümün ilk hücresini kullanıyorum, bu çözüm çok temiz görünmüyor, ancak çok iyi çalışıyor, üstbilgiler bölümünüz için tanımlanmış bir prototip hücre ve cellForRowAtIndexPath yönteminde kullanabilirsiniz indexPath.row == 0 isteyin, doğruysa başlık bölümü prototip hücresini kullanın, aksi takdirde varsayılan prototip hücrenizi kullanın.


Hala indexPath.row& ile çalışmak istiyorsanız , başlıklarınızın görünmez indexPath.sectionolması 0.0fiçin için bir yükseklik döndürdüğünüzden emin olun - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section.
Çorbası

4

TableView Stilinizi değiştirin:

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

UITableView için apple belgelerine göre:

UITableViewStylePlain- Düz tablo görünümü. Tüm bölüm üstbilgileri veya altbilgileri, satır görünümü ayırıcıları olarak görüntülenir ve tablo görünümü kaydırıldığında yüzer.

UITableViewStyleGrouped- Bölümleri farklı satır grupları sunan tablo görünümü. Bölüm üstbilgileri ve altbilgileri yüzmez. Umarım bu küçük değişiklik size yardımcı olur ..


2

Gruplandırılmış stil temel olarak iOS 7'deki (düzlük ve arka plan açısından) düz stille aynı görünüme göre, bizim için en iyi ve en kolay (yani en az hacky) düzeltme, tablo görünümünün stilini gruplandırılmış olarak değiştirmekti. En üste kaydırmalı gezinti çubuğunu entegre ettiğimizde, setler her zaman bir sorundu. Gruplandırılmış tablo görünümü stili ile (hücrelerimizle) tamamen aynı görünür ve bölüm başlıkları sabit kalır. Kaydırma tuhaflığı yok.


Bu, özellikle hücreler özelse en iyi çözümdür, kaydırma üste çarptığında bölüm başlığının "bekletilmesini" durdurmuş gibi görünür.
Geri dönüştürülmüş çelik

1

TableView öğenize negatif bir iç metin atayın. 22px'lik yüksek bölüm başlıklarınız varsa ve bunların yeniden eklenmesinden hemen sonra yapışkan olmasını istemiyorsanız, Data add:

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

Benim için bir cazibe gibi çalışıyor. Bölüm altbilgileri için de çalışır, bunun yerine alt kısımdaki negatif metni girin.


Bu sadece ilk başlığı keser ??
cannyboy

Benim için mükemmel çalıştı !! Teşekkürler
Daniel

0

Tabloyu Kaydırma Görünümü'ne ekliyorum ve bu iyi çalışıyor gibi görünüyor.


0

Cevabımı buradan kontrol edin . Bu, kayan bölüm olmayan başlıkları herhangi bir korsan olmadan uygulamak için en kolay yoldur.


0

@ LocoMike'ın cevabı benim tableView en uygun, ancak altbilgileri de kullanırken kırdı. Bu, üstbilgi ve altbilgiyi kullanırken düzeltilmiş çözümdür:

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

@Awulf cevap hızlı sürümü, harika çalışıyor!

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

Ben sadece tableHeaderView özelliği ayarlama, yani öğrendim:

 tableView.tableHeaderView = customView;

ve bu kadar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.