2013-03-04 17 views

risposta

13

Il problema con l'utilizzo indexPathsForVisibleRows è che non comprende sezioni senza alcuna riga. Per ottenere tutte le sezioni visibili, tra cui le sezioni vuote si deve controllare la rect della sezione e confrontarlo con il contentOffset del tavolo.

Hai anche a prestare attenzione alla differenza tra lo stile semplice con sezioni galleggianti e lo stile raggruppati, senza sezioni galleggianti.

ho fatto una categoria che supportano questo calcolo:

@interface UITableView (VisibleSections) 

// Returns an array of NSNumbers of the current visible section indexes 
- (NSArray *)indexesOfVisibleSections; 
// Returns an array of UITableViewHeaderFooterView objects of the current visible section headers 
- (NSArray *)visibleSections; 

@end 

@implementation UITableView (VisibleSections) 

- (NSArray *)indexesOfVisibleSections { 
    // Note: We can't just use indexPathsForVisibleRows, since it won't return index paths for empty sections. 
    NSMutableArray *visibleSectionIndexes = [NSMutableArray arrayWithCapacity:self.numberOfSections]; 
    for (int i = 0; i < self.numberOfSections; i++) { 
     CGRect headerRect; 
     // In plain style, the section headers are floating on the top, so the section header is visible if any part of the section's rect is still visible. 
     // In grouped style, the section headers are not floating, so the section header is only visible if it's actualy rect is visible. 
     if (self.style == UITableViewStylePlain) { 
      headerRect = [self rectForSection:i]; 
     } else { 
      headerRect = [self rectForHeaderInSection:i]; 
     } 
     // The "visible part" of the tableView is based on the content offset and the tableView's size. 
     CGRect visiblePartOfTableView = CGRectMake(self.contentOffset.x, self.contentOffset.y, self.bounds.size.width, self.bounds.size.height); 
     if (CGRectIntersectsRect(visiblePartOfTableView, headerRect)) { 
      [visibleSectionIndexes addObject:@(i)]; 
     } 
    } 
    return visibleSectionIndexes; 
} 

- (NSArray *)visibleSections { 
    NSMutableArray *visibleSects = [NSMutableArray arrayWithCapacity:self.numberOfSections]; 
    for (NSNumber *sectionIndex in self.indexesOfVisibleSections) { 
     UITableViewHeaderFooterView *sectionHeader = [self headerViewForSection:sectionIndex.intValue]; 
     [visibleSects addObject:sectionHeader]; 
    } 

    return visibleSects; 
} 

@end 
4

Per una tabella stile semplice, è possibile ottenere le righe visibili. Da quelli, ottieni l'insieme delle sezioni visibili. E da quello, ottenere le viste dell'intestazione della sezione dalla tabella.

NSArray *visibleRows = [self.tableView indexPathsForVisibleRows]; 
NSMutableIndexSet *sections = [[NSMutableIndexSet alloc] init]; 
for (NSIndexPath *indexPath in visibleRows) { 
    [sections addIndex:indexPath.section]; 
} 

NSMutableArray *headerViews = [NSMutableArray array]; 
[sections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { 
    UIView *view = [self.tableView headerViewForSection:idx]; 
    [headerViews addObject:view]; 
}]; 

Nota: codice non testato - può contenere errori di battitura. Questo non funzionerà al 100% per una tabella di stili raggruppati.

+1

non funziona se la sezione non ha righe –

+1

@PeterLapisu Vero ma non si dovrebbe mostrare un'intestazione di sezione per una sezione senza righe, quindi questo non sarà un problema. – rmaddy

+1

dipende dal caso, ho appena incontrato una situazione del genere :)) –

1

In questo caso, penso che si imposta il cell.tag alla sezione corrente (indexPath.section) nella cellForRowAtIndexPath e utilizza il metodo visibleCells come hai descritto e headerViewForSection.

6

Mi è piaciuto molto @ soluzione adamsiton e ho finito per tradurlo a rapida. Eccolo, Cordiali saluti.

ho chiamato il file UITableView + VisibleSections.swift

import UIKit 

public extension UITableView { 

    var indexesOfVisibleSections: [Int] { 
     // Note: We can't just use indexPathsForVisibleRows, since it won't return index paths for empty sections. 
     var visibleSectionIndexes = [Int]() 

     for i in 0..<numberOfSections { 
      var headerRect: CGRect? 
      // In plain style, the section headers are floating on the top, so the section header is visible if any part of the section's rect is still visible. 
      // In grouped style, the section headers are not floating, so the section header is only visible if it's actualy rect is visible. 
      if (self.style == .plain) { 
       headerRect = rect(forSection: i) 
      } else { 
       headerRect = rectForHeader(inSection: i) 
      } 
      if headerRect != nil { 
       // The "visible part" of the tableView is based on the content offset and the tableView's size. 
       let visiblePartOfTableView: CGRect = CGRect(x: contentOffset.x, y: contentOffset.y, width: bounds.size.width, height: bounds.size.height) 
       if (visiblePartOfTableView.intersects(headerRect!)) { 
        visibleSectionIndexes.append(i) 
       } 
      } 
     } 
     return visibleSectionIndexes 
    } 

    var visibleSectionHeaders: [UITableViewHeaderFooterView] { 
     var visibleSects = [UITableViewHeaderFooterView]() 
     for sectionIndex in indexesOfVisibleSections { 
      if let sectionHeader = headerView(forSection: sectionIndex) { 
       visibleSects.append(sectionHeader) 
      } 
     } 

     return visibleSects 
    } 
} 
2

La soluzione da Benjamin Wheeler è una grande soluzione Swift. Ho risolto un problema a causa di nuova sintassi Swift, e modificato in modo che corrisponda alla proprietà .visibleCells fornita dalla implementazione di default UITableView.

extension UITableView { 

    /// The table section headers that are visible in the table view. (read-only) 
    /// 
    /// The value of this property is an array containing UITableViewHeaderFooterView objects, each representing a visible cell in the table view. 
    /// 
    /// Derived From: [http://stackoverflow.com/a/31029960/5191100](http://stackoverflow.com/a/31029960/5191100) 
    var visibleSectionHeaders: [UITableViewHeaderFooterView] { 
     get { 
      var visibleSects = [UITableViewHeaderFooterView]() 

      for sectionIndex in indexesOfVisibleSections() { 
       if let sectionHeader = self.headerViewForSection(sectionIndex) { 
        visibleSects.append(sectionHeader) 
       } 
      } 

      return visibleSects 
     } 
    } 

    private func indexesOfVisibleSections() -> Array<Int> { 
     // Note: We can't just use indexPathsForVisibleRows, since it won't return index paths for empty sections. 
     var visibleSectionIndexes = Array<Int>() 

     for (var i = 0; i < self.numberOfSections; i++) { 
      var headerRect: CGRect? 
      // In plain style, the section headers are floating on the top, 
      // so the section header is visible if any part of the section's rect is still visible. 
      // In grouped style, the section headers are not floating, 
      // so the section header is only visible if it's actual rect is visible. 
      if (self.style == .Plain) { 
       headerRect = self.rectForSection(i) 
      } else { 
       headerRect = self.rectForHeaderInSection(i) 
      } 

      if headerRect != nil { 
       // The "visible part" of the tableView is based on the content offset and the tableView's size. 
       let visiblePartOfTableView: CGRect = CGRect(
        x: self.contentOffset.x, 
        y: self.contentOffset.y, 
        width: self.bounds.size.width, 
        height: self.bounds.size.height 
       ) 

       if (visiblePartOfTableView.intersects(headerRect!)) { 
        visibleSectionIndexes.append(i) 
       } 
      } 
     } 

     return visibleSectionIndexes 
    } 
} 
1

per ottenere sezioni visibili attuali, u potrebbe ottenere controllando le celle visibili attuali indexpath sezione, quindi questa funzione potrebbe ritornare u sezioni visibili

- (NSArray *)indexesOfVisibleSections { 

    NSMutableArray *visibleSections = [NSMutableArray array]; 

    for (UITableViewCell * cell in [self.tableView visibleCells]) { 
     if (![visibleSections containsObject:[NSNumber numberWithInteger:[self.tableView indexPathForCell:cell].section]]) { 
      [visibleSections addObject:[NSNumber numberWithInteger:[self.tableView indexPathForCell:cell].section]]; 
     } 
    } 

    return visibleSections; 
} 

E per accedere vista in sezione, u possibile utilizzare

- (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section; 
+0

non tiene conto di un'intestazione che non contiene celle – kgaidis

+0

@kgaidis l'hai testato? logica in questo modo che ottiene la sezione cella visibile, indipendentemente dal suo tipo, quindi se hai 3 sezioni, ognuna ha 1 riga, quindi controlla la matrice di righe visibili e ottiene quelle sezioni di righe e la aggiunge alla matrice di sezioni visibili, non ha nulla a che fare con il tipo di intestazione della sezione, la vista o la cella – Mortgy

+0

"Ognuno ha 1 riga". Ecco dove fallisce. Una sezione può esistere, con una vista di intestazione visibile, che non ha celle. Se una sezione non ha celle, allora non farà parte di 'visibleCells', che è ciò su cui si basa interamente questo algoritmo. – kgaidis

0

Un rapido sguardo alla documentazione UITableView ci dà la indexPathsForVisibleRows e combinandolo con la mappa ci dà l'array che abbiamo NE ed .:

tableView.indexPathsForVisibleRows.map{ tableView.headerView(forSection: $0.section) } 

map restituisce l'array della nostra intestazione visibile nella sezione.

Problemi correlati