2013-03-04 33 views

Trả lời

13

Sự cố khi sử dụng indexPathsForVisibleRows là vấn đề không bao gồm các phần không có bất kỳ hàng nào. Để có được tất cả các phần có thể nhìn thấy, bao gồm cả các phần trống, bạn phải kiểm tra trực tiếp của phần và so sánh nó với contentOffset của bảng.

Bạn cũng phải chú ý đến sự khác biệt giữa kiểu đồng bằng với các phần nổi và kiểu được nhóm mà không có phần nổi.

tôi đã thực hiện một thể loại có hỗ trợ tính toán này:

@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

Đối với bảng kiểu đồng bằng, bạn có thể nhận được các hàng hiển thị. Từ đó, nhận được tập hợp các phần hiển thị. Và từ đó, có được các khung nhìn tiêu đề phần từ bảng.

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

Lưu ý: mã không được kiểm tra - có thể chứa lỗi chính tả. Điều này sẽ không hoạt động 100% cho một bảng kiểu được nhóm.

+1

không hoạt động nếu phần không có hàng –

+1

@PeterLapisu Đúng nhưng bạn không nên hiển thị tiêu đề phần cho phần không có hàng nên đây không phải là vấn đề. – rmaddy

+1

phụ thuộc vào trường hợp, tôi chỉ gặp phải tình huống như vậy :)) –

1

Trong trường hợp này, tôi nghĩ rằng bạn thiết lập các cell.tag đến phần hiện tại (indexPath.section) trong cellForRowAtIndexPath và sử dụng phương pháp visibleCells như bạn mô tả và headerViewForSection.

6

Tôi thực sự thích @ giải pháp adamsiton và tôi đã kết thúc dịch nó để nhanh chóng. Đây là, FYI.

tôi gọi là tập tin 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

Các giải pháp của Benjamin Wheeler là một giải pháp Swift tuyệt vời. Tôi đã khắc phục sự cố trong đó do cú pháp Swift mới và sửa đổi nó để khớp với thuộc tính .visibleCells được cung cấp bởi triển khai UITableView mặc định.

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

để có được những phần có thể nhìn thấy hiện tại, u có thể nhận được nó bằng cách kiểm tra các tế bào có thể nhìn thấy hiện tại indexPath phần, vì vậy chức năng này có thể quay trở lại u các phần có thể nhìn thấy

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

Và để truy cập vào xem phần, u có thể sử dụng

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

không tính đến tiêu đề không chứa ô nào – kgaidis

+0

@kgaidis u kiểm tra? logic ở đây là nó lấy phần ô nhìn thấy được, bất kể là kiểu nào, vì vậy nếu u có 3 phần, mỗi phần có 1 hàng, sau đó nó kiểm tra mảng hàng có thể nhìn thấy và nhận được các phần hàng đó và thêm nó vào mảng các phần hiển thị, nó không có gì để làm với loại tiêu đề phần, xem hoặc tế bào – Mortgy

+0

"Mỗi người có 1 hàng." Đó là nơi nó thất bại. Một phần có thể tồn tại, với chế độ xem tiêu đề hiển thị, không có ô nào. Nếu một phần không có ô, thì nó sẽ không là một phần của 'visibleCells', mà thuật toán này hoàn toàn dựa vào. – kgaidis

0

Một cái nhìn lướt qua tài liệu UITableView cho chúng ta indexPathsForVisibleRows và kết hợp nó với bản đồ cho chúng ta mảng chúng ta ne ed:

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

Bản đồ trả về mảng của tiêu đề có thể nhìn thấy trong phần của chúng tôi.

Các vấn đề liên quan