6

Ich implementiere einen unbegrenzt scrollenden Kalender. Mein Problem ist, dass ich den aktuellen Monat als Titel in der Navigationsleiste festlegen möchte und er sollte während des Scrollens aktualisiert werden - sobald Sie die Abschnittsüberschriftenansicht übergeben, sollte der Titel in der Navigationsleiste aktualisiert werden.Wie erkennt man das Scrollen zu einem neuen Abschnitt in einer UICollectionView?

Eine mögliche Lösung wäre, den Ansichtstitel in der Methode - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath zu setzen, so dass, wenn ich einen neuen Abschnitt Header berechnen, es auch den Titel aktualisiert. Das Problem dabei ist, dass sich der Titel ändert, wenn sich der neue Abschnitt unten auf der Seite befindet.

Currently displaying the Section Header as title, not optimal

Gibt es eine Möglichkeit, den „aktuellen Bereich“ von UICollectionView zu wissen, wenn der Benutzer es gescrollt hat? Oder können Sie sich einen Weg vorstellen, um meine derzeitige Lösung zu verbessern?

Um den Lesern dieses Beitrags zu helfen, postete ich meinen eigenen Beispielcode für diese Frage an diesem GitHub repo.

+0

Haben Sie eine Lösung gefunden, um das gewünschte Verhalten zu erzielen? – Joey

+0

Hallo @Joey überprüfe meine Antwort. – KDeogharkar

Antwort

0

Änderung unter der Linie in Methode viewForSupplementaryElementOfKind:

self.title = [df stringFromDate:[self dateForFirstDayInSection:indexPath.section]]; 

dazu:

if(![[self dateForFirstDayInSection:indexPath.section-1] isKindOfClass:[NSNull class]]){ 
     self.title = [df stringFromDate:[self dateForFirstDayInSection:indexPath.section-1]]; 
} 

Hoffe, es wird Ihnen helfen.

+0

Ja, das hat das spezifische Problem gelöst. Vielen Dank! – maggix

+0

Dies funktioniert nicht, wenn die nächste Kopfzeile nicht auf dem Bildschirm angezeigt wird. Wenn Sie nach oben scrollen, ändert sich der Titel, bevor der vorherige Abschnitt sichtbar ist. – Joey

0

Ja, das Problem ist, dass Fußzeile und Header nicht in der visibleCells-Auflistung vorhanden sind. Es gibt eine andere Möglichkeit, Scroll für Abschnitt Header/Footer zu erkennen. Fügen Sie einfach ein Steuerelement hinzu und finden Sie das richtige dafür. Wie folgt aus:

func scrollViewDidScroll(scrollView: UIScrollView) { 

    if(footerButton.tag == 301) 
    { 
     let frame : CGRect = footerButton.convertRect(footerButton.frame, fromView: self.view) 
     //some process for frame 
    } 


} 
2

Ich habe darüber nachgedacht, einen Algorithmus, die Sie erlauben würden, zu wissen, wann der Benutzer an einem Abschnitt Header, um den Titel zu aktualisieren gescrollt hat, und nach einigen Experimenten habe ich herausgefunden, wie zu implementieren, die gewünschtes Verhalten.

Im Prinzip müssen Sie jedes Mal, wenn sich die Scroll-Position ändert, wissen, in welchem ​​Bereich sich der Benutzer befindet, und den Titel aktualisieren. Sie tun dies über scrollViewDidScroll auf der UIScrollViewDelegate - Erinnerung an eine Sammlungsansicht ist eine Bildlaufansicht. Überstreichen Sie alle Überschriften und suchen Sie diejenige, die der aktuellen Bildlaufposition am nächsten ist, ohne einen negativen Versatz zu haben. Um dies zu tun, habe ich eine Eigenschaft verwendet, die ein Array der Position jedes Abschnittsheaders speichert. Wenn ein Header erstellt wird, speichere ich seine Position im Array am entsprechenden Index. Sobald Sie die Kopfzeile gefunden haben, die Ihrer Scroll-Position (oder der Indexposition dieser Kopfzeile) am nächsten ist, aktualisieren Sie einfach den Titel in der Navigationsleiste mit dem entsprechenden Titel.

In viewDidLoad, füllen Sie die Array-Eigenschaft mit NSNull für jeden Abschnitt Sie haben:

self.sectionHeaderPositions = [[NSMutableArray alloc] init]; 
for (int x = 0; x < self.sectionTitles.count; x++) { 
    [self.sectionHeaderPositions addObject:[NSNull null]]; 
} 

In collectionView:viewForSupplementaryElementOfKind:atIndexPath:, aktualisieren Sie das Array mit der Position der Kopfsicht erstellt:

NSNumber *position = [NSNumber numberWithFloat:headerView.frame.origin.y + headerView.frame.size.height]; 
[self.sectionHeaderPositions replaceObjectAtIndex:indexPath.section withObject:position]; 

In scrollViewDidScroll: Führen Sie die Berechnungen aus, um zu bestimmen, welcher Titel für diese Bildlaufposition angezeigt werden soll:

CGFloat currentScrollPosition = self.collectionView.contentOffset.y + self.collectionView.contentInset.top; 
CGFloat smallestPositiveHeaderDifference = CGFLOAT_MAX; 
int indexOfClosestHeader = NSNotFound; 

//find the closest header to current scroll position (excluding headers that haven't been reached yet) 
int index = 0; 
for (NSNumber *position in self.sectionHeaderPositions) { 
    if (![position isEqual:[NSNull null]]) { 
     CGFloat floatPosition = position.floatValue; 
     CGFloat differenceBetweenScrollPositionAndHeaderPosition = currentScrollPosition - floatPosition; 
     if (differenceBetweenScrollPositionAndHeaderPosition >= 0 && differenceBetweenScrollPositionAndHeaderPosition <= smallestPositiveHeaderDifference) { 
      smallestPositiveHeaderDifference = differenceBetweenScrollPositionAndHeaderPosition; 
      indexOfClosestHeader = index; 
     } 
    } 
    index++; 
} 
if (indexOfClosestHeader != NSNotFound) { 
    self.currentTitle.text = self.sectionTitles[indexOfClosestHeader]; 
} else { 
    self.currentTitle.text = self.sectionTitles[0]; 
} 

Dadurch wird der Titel in der Navigationsleiste korrekt aktualisiert, sobald der Benutzer über die Kopfzeile eines Abschnitts scrollt.Wenn sie zurück scrollen, wird sie ebenfalls korrekt aktualisiert. Außerdem wird der Titel korrekt festgelegt, wenn sie nicht über den ersten Abschnitt hinaus geblättert haben. Es ist jedoch nicht sehr gut mit der Rotation. Es wird auch nicht gut funktionieren, wenn Sie dynamischen Inhalt haben, der dazu führen kann, dass die gespeicherten Positionen der Header-Ansichten falsch sind. Und wenn Sie das Springen zu einem bestimmten Abschnitt unterstützen, springt der Benutzer zu einem Abschnitt, dessen Abschnittsheader des vorherigen Abschnitts noch nicht erstellt wurde, und dieser Abschnitt ist nicht groß genug, sodass sich der Abschnittskopf unterhalb der Navigationsleiste befindet (der letzte Abschnitt) vielleicht), wird der falsche Titel in der Navigationsleiste angezeigt.

Wenn jemand dies verbessern kann, um es effizienter oder sonst besser zu machen bitte tun und ich werde die Antwort entsprechend aktualisieren.

+0

Hallo Joey, danke für die ausgearbeitete Antwort! – maggix