Cách ẩn tiêu đề phần đầu tiên trong UITableView (kiểu nhóm)


108

Vì thiết kế dạng xem bảng sử dụng kiểu nhóm đã thay đổi đáng kể với iOS 7, tôi muốn ẩn (hoặc xóa) tiêu đề phần đầu tiên. Cho đến nay tôi vẫn chưa đạt được nó.

Được đơn giản hóa một chút, mã của tôi trông như thế này:

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 0)
        return 0.0f;
    return 32.0f;
}

- (UIView*) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        UIView* view = [[UIView alloc] initWithFrame: CGRectMake(0.0f, 0.0f, 640.0f, 0.0f)];
        return view;
    }
    return nil;
}

- (NSString*) tableView:(UITableView *) tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return nil;
    } else {
        // return some string here ...
    }
}

Nếu tôi trả về chiều cao là 0, hai phương thức khác sẽ không bao giờ được gọi với chỉ mục phần 0. Tuy nhiên, một tiêu đề phần trống vẫn được vẽ với chiều cao mặc định. (Trong iOS 6, hai phương thức được gọi. Tuy nhiên, kết quả hiển thị là giống nhau.)

Nếu tôi trả về một giá trị khác, tiêu đề phần sẽ có chiều cao được chỉ định.

Nếu tôi trả về 0,01, nó gần như chính xác. Tuy nhiên, khi tôi bật "Hình ảnh bị lệch màu" trong trình mô phỏng, nó sẽ đánh dấu tất cả các ô xem bảng (có vẻ là một hệ quả hợp lý).

Các câu trả lời cho câu hỏi UITableView: ẩn tiêu đề khỏi phần trống dường như chỉ ra rằng một số người đã thành công trong việc ẩn tiêu đề phần. Nhưng nó có thể áp dụng cho kiểu đơn giản (thay vì kiểu được nhóm lại).

Sự thỏa hiệp tốt nhất cho đến nay là trả lại chiều cao 0,5, dẫn đến một đường kẻ hơi dày hơn bên dưới thanh điều hướng. Tuy nhiên, tôi sẽ đánh giá cao nếu ai đó biết làm thế nào mà tiêu đề phần đầu tiên có thể bị ẩn hoàn toàn.

Cập nhật

Theo phân tích của caglar ( https://stackoverflow.com/a/19056823/413337 ), vấn đề chỉ nảy sinh nếu chế độ xem bảng được chứa trong bộ điều khiển điều hướng.


Tôi không hiểu phần đó => if (section == 0) return view; trả về con số không; tức là trả về một chế độ xem khi nó là phần đầu tiên và bằng không?
Zen

Ý tưởng là trả về một dạng xem có chiều cao bằng 0 cho phần đầu tiên và trả về nil cho tất cả các phần khác để dạng xem bảng sử dụng dạng xem tiêu đề mặc định cho chúng. Phần nil hoạt động độc đáo; chế độ xem bảng hiển thị tiêu đề cho các phần này. Nhưng phần cho phần 0 là không liên quan vì phương thức không bao giờ được gọi với section == 0.
Codo

1
Câu trả lời này có vẻ ngắn gọn và ngọt ngào. stackoverflow.com/a/23955420/3965
Mr Rogers

Câu trả lời:


154

Tôi có một cách giải quyết có vẻ hợp lý với tôi. Vì vậy, tôi đang trả lời câu hỏi của riêng tôi.

Vì 0 vì chiều cao của tiêu đề phần đầu tiên không hoạt động, tôi trả về 1. Sau đó, tôi sử dụng contentInset để ẩn chiều cao đó bên dưới thanh điều hướng.

Mục tiêu-C:

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 0)
            return 1.0f;
    return 32.0f;
}

- (NSString*) tableView:(UITableView *) tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return nil;
    } else {
        // return some string here ...
    }
}

- (void) viewDidLoad
{
    [super viewDidLoad];

     self.tableView.contentInset = UIEdgeInsetsMake(-1.0f, 0.0f, 0.0f, 0.0);
}

Nhanh:

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return section == 0 ? 1.0 : 32
}

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.contentInset = UIEdgeInsets(top: -1, left: 0, bottom: 0, right: 0)
}

6
Sử dụng chiều cao tiêu đề 0,1f thậm chí còn tốt hơn để ẩn nó.
Chuck Krutsinger

4
Tôi đã thử sử dụng 0,1f. Nhưng kết quả là các bản vẽ không còn được căn chỉnh theo pixel, gây ra hiện tượng mờ và giảm hiệu suất. Chỉ cần thử nó trong trình mô phỏng: nó có một tùy chọn để làm nổi bật sự liên kết có vấn đề.
Codo

31
Trên thực tế, một cách triển khai tốt hơn (ít có khả năng bị phá vỡ hơn trong tương lai) là sử dụng CGFLOAT_MINthay vì một giá trị được mã hóa cứng. Nói cách khác, không return 1.0fhoặc 0.1fthay vào đó, return CGFLOAT_MINNếu Apple thay đổi giá trị tối thiểu có thể chấp nhận được, bạn sẽ có mã để thay đổi nếu bạn nhập mã cố định giá trị trả về. Ngoài ra, bạn không biết liệu mình có đang sử dụng giá trị nhỏ nhất có thể hay không. Sử dụng hằng số đã xác định, bạn được đảm bảo đang sử dụng giá trị nhỏ nhất có thể và mã của bạn sẽ tồn tại trước những thay đổi của hệ điều hành.
Chris Ostmo

11
@Chris: e rằng bạn không hiểu ý. Tôi không trả về một giá trị rất nhỏ mà là bội số của kích thước pixel để bản vẽ vẫn được căn chỉnh pixel (để có hiệu suất tốt và sắc nét). Sau đó, tôi bù đắp nó bằng cách sử dụng nội dung. Điều này khó có thể thay đổi trong tương lai vì nó là một khoảng cách đáng kể, có thể nhìn thấy được và không phải là điều mà hệ điều hành có thể bỏ qua.
Codo

8
+1 Vì không sử dụng giá trị pixel phân số làm hiệu số giao diện người dùng.
Ricardo Sanchez-Saez

52

Đây là cách ẩn tiêu đề phần đầu tiên trong UITableView (kiểu nhóm).

Giải pháp Swift 3.0 & Xcode 8.0

  1. Người đại diện của TableView nên triển khai phương thức heightForHeaderInSection

  2. Trong phương thức heightForHeaderInSection, trả về số dương nhỏ nhất. (không phải không!)

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    
        let headerHeight: CGFloat
    
        switch section {
        case 0:
            // hide the header
            headerHeight = CGFloat.leastNonzeroMagnitude
        default:
            headerHeight = 21
        }
    
        return headerHeight
    }

6
trả về CGFloat.leastNonzeroMagosystem thay vì 0 đã giúp tôi. Cảm ơn!
anoo_radha

Câu trả lời hoàn hảo, Cảm ơn
Pierre

Nhân tiện, CGFLOAT_MINđối với objc giống hệt CGFloat.leastNonzeroMagnitudetrong Swift
DawnSong 21/02/19

36

Câu trả lời rất hài hước cho tôi và nhóm của tôi, và nó hoạt động như một cái duyên

  • Trong Trình tạo giao diện, Chỉ cần di chuyển dạng xem bảng dưới dạng xem khác trong hệ thống phân cấp dạng xem.

LÝ DO:

Chúng tôi nhận thấy rằng điều này chỉ xảy ra cho Chế độ xem đầu tiên trong Chế độ xem thứ bậc, nếu chế độ xem đầu tiên này là một UITableView . Vì vậy, tất cả các UITableView tương tự khác không có phần gây khó chịu này, ngoại trừ phần đầu tiên. Chúng tôi đã thử di chuyển UITableView ra khỏi vị trí đầu tiên trong phân cấp chế độ xem và mọi thứ đều hoạt động như mong đợi.


1
Bạn vẫn có hiệu ứng kính mờ của thanh điều hướng khi cuộn chế độ xem bảng chứ?
Codo

Bạn sẽ có hiệu ứng mờ này khi thiết lập tableView của mình cho phù hợp. Bạn cần đặt contentInsetví dụ như {0, 64, 0, 0}để có độ lệch 64px từ trên cùng (thanh trạng thái cộng với thanh điều hướng). Các tableView cần phải được gắn ở phía trên cùng màn hình, chứ không phải topLayoutGuide (để cho nó đạt dưới thanh nav)
Julian F. Weinert

Nếu bạn không sử dụng kéo để làm mới, điều này sẽ ổn.
Michael

2
Chà. Điều này đã làm việc cho tôi trong iOS 9 và chỉ thổi bay tâm trí của tôi.
phân bổ

Đây phải là câu trả lời được chấp nhận. Thật là một lỗi kỳ lạ!
Oded Harth

25

Sử dụng thủ thuật này cho tableView loại được nhóm

Sao chép dán mã bên dưới cho chế độ xem bảng của bạn trong phương thức viewDidLoad :

tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tableView.bounds.size.width, 0.01f)];

Tôi chưa thử nhưng tôi nghi ngờ giải pháp này có nhược điểm giống như một số giải pháp được đề xuất khác: bản vẽ không còn được căn chỉnh theo pixel, gây ra hiện tượng mờ và giảm hiệu suất. Trình mô phỏng có thể tiết lộ điều đó: nó có một tùy chọn để làm nổi bật sự liên kết có vấn đề. Tuy nhiên, nếu nó làm tròn xuống 0, thì đó thực sự là một giải pháp tốt.
Codo

Có, tôi đoán nó làm tròn xuống 0. Bởi vì tôi đã sử dụng nó nhiều lần, nhưng không tìm thấy bất kỳ vết mờ nào trong bản vẽ.
Nitesh Borad

Chế độ xem TableHeader và Chế độ xem tiêu đề phần? sự khác biệt là gì,
AsifHabib

Hoặc hơi ngắn hơn: _tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)].
mojuba

@AsifHabib: tableHeaderView được đặt ở đầu tất cả các phần tử bảng. Đó là chế độ xem tiêu đề cho chính bảng. Và chế độ xem tiêu đề phần là chế độ xem được đặt trên mỗi phần. Có thể có nhiều dạng xem tiêu đề phần theo số phần được chỉ định trong bảng. Tuy nhiên, sẽ chỉ có một chế độ xem tiêu đề bảng.
Nitesh Borad,

21

cách này là OK.

override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if section == 0 {
        return CGFloat.min
    }
    return 25
}

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    if section == 0 {
        return nil
    }else {
        ...
    }
}

2
Đây là một biến thể tốt của giải pháp của tôi ngoại trừ nó sử dụng các giá trị phân số. Bằng cách đó, văn bản và hình ảnh không còn được căn chỉnh theo pixel, quá trình vẽ bị chậm lại và kết quả có thể bị mờ. Trình mô phỏng có tùy chọn "Hình ảnh bị lệch màu" để tiết lộ vấn đề này.
Codo,

Làm việc tốt cho những người như tôi sử dụng tế bào tĩnh với một containerView
Thibaut noah

3
Swift 3> 'CGFloat.min' đã được đổi tên thành 'CGFloat.leastNormalMagosystem'
rjobidon

6

Tôi vừa sao chép mã của bạn và thử. Nó chạy bình thường (đã thử trong giả lập). Tôi đính kèm kết quả xem. Bạn muốn xem như vậy, phải không? Hay tôi hiểu sai vấn đề của bạn?

nhập mô tả hình ảnh ở đây


1
Vâng, về cơ bản đó là những gì tôi muốn, ngoại trừ chế độ xem bảng của tôi nằm trong bộ điều khiển điều hướng. Điều đó có thể tạo ra sự khác biệt?
Codo

2
Tôi đã thêm tableView vào bộ điều khiển điều hướng và tình huống của bạn xuất hiện :) Tôi nghĩ rằng trong iOS 7, chiều cao tiêu đề này được sửa chữa theo mặc định trong chế độ xem bảng kiểu nhóm. Bằng cách thay đổi khung của tableView, chế độ xem tiêu đề đầu tiên có thể bị ẩn. (Như set x = 0 y = -40). Tuy nhiên, tôi biết giải pháp này không phải là một giải pháp tốt.
caglar, 27/09/13

1
Cảm ơn bạn rất nhiều vì việc làm của bạn. Vì vậy, có vẻ như vấn đề chỉ phát sinh nếu chế độ xem bảng sử dụng kiểu được nhóm theo kiểu và được chứa trong bộ điều khiển điều hướng.
Codo

Đang cố gắng thay đổi từ bộ điều khiển chế độ xem sang bộ điều khiển chế độ xem bảng Tôi không thể khắc phục sự cố với tiêu đề. Có lẽ tôi đang thiếu một cái gì đó khi cố gắng chuyển đổi nó. (iOS 7.0.3 sim)
Evgeni Petrov

1
Vấn đề này cũng xuất hiện trong ảnh chụp nhanh này! ô thứ 0 không bắt đầu từ x: 0.0f & y: 0.0f.
Burhanuddin Sunelwala

6

Swift3: heightForHeaderInSection hoạt động với 0, bạn chỉ cần đảm bảo tiêu đề được đặt thành clipsToBounds.

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
       return 0
}

nếu bạn không đặt clipToBounds tiêu đề ẩn sẽ hiển thị khi cuộn.

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    guard let header = view as? UITableViewHeaderFooterView else { return }

    header.clipsToBounds = true
}

1
clipsToBound = true rất quan trọng nếu bạn định ẩn hoàn toàn chế độ xem tiêu đề phần. Đặt chiều cao của nó thành 0 / CGFLOAT_MIN là không đủ.
Altimac

5

Cập nhật [19/9/17]: Câu trả lời cũ không hoạt động với tôi nữa trong iOS 11. Cảm ơn Apple. Những điều sau đã làm:

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionHeaderHeight = 20.0f;
self.tableView.contentInset = UIEdgeInsetsMake(-18.0, 0.0f, 0.0f, 0.0);

Câu trả lời trước:

Như đã đăng trong các bình luận của Chris Ostomo, những điều sau đây đã làm việc cho tôi:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return CGFLOAT_MIN; // to get rid of empty section header
}

Tôi nghi ngờ rằng nội dung của chế độ xem bảng của bạn không còn được căn chỉnh theo pixel, gây ra hiện tượng mờ và giảm hiệu suất. Trình mô phỏng có thể tiết lộ điều đó: nó có một tùy chọn để làm nổi bật sự liên kết có vấn đề. Tuy nhiên, nếu nó làm tròn xuống 0, thì đó thực sự là một giải pháp tốt.
Codo

Không, tôi không nhận thấy bất kỳ vấn đề nội dung nào. Các ràng buộc dường như ổn.
Manindra Moharana

1
Hoan nghênh! Không hoạt động trong iOS 11 nữa! Sửa chữa của tôi kéo dài chưa đầy một tuần .. 😞
Manindra Moharana

4

Dưới đây là cách loại bỏ tiêu đề phần trên cùng trong UITableView được nhóm, trong Swift:

tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))

3

Trong Swift 4.2 và nhiều phiên bản trước đó, thay vì đặt chiều cao của tiêu đề đầu tiên thành 0 như trong các câu trả lời khác, bạn chỉ có thể đặt các tiêu đề khác thành nil. Giả sử bạn có hai phần và chỉ muốn phần thứ hai (tức là 1) có tiêu đề. Tiêu đề đó sẽ có văn bản Foobar :

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return section == 1 ? "Foobar" : nil
}

3

Hãy thử điều này nếu bạn muốn xóa hoàn toàn tất cả tiêu đề phần

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}

Đó chỉ là tôi cần. Một giải pháp đơn giản và dễ dàng. 1+
iGhost

0

Tôi chưa thể bình luận nhưng nghĩ rằng tôi sẽ thêm rằng nếu bạn có UISearchControllertrên bộ điều khiển của bạn với UISearchBarnhư của bạn tableHeaderView, việc đặt chiều cao của phần đầu tiên là 0 in heightForHeaderInSectionthực sự hoạt động.

Tôi sử dụng self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height);để thanh tìm kiếm bị ẩn theo mặc định.

Kết quả là không có tiêu đề cho phần đầu tiên và cuộn xuống sẽ hiển thị thanh tìm kiếm ngay trên hàng đầu tiên.


0

dễ nhất là quay lại nilhoặc ""vào func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?phần mà bạn không muốn hiển thị tiêu đề.


0

Phiên bản Swift: Swift 5.1
Hầu hết, bạn có thể đặt chiều cao trong ủy nhiệm tableView như sau:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
   return UIView(frame: CGRect(x: 0, y: 0, width: view.width, height: CGFloat.leastNormalMagnitude))
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
   return CGFloat.leastNormalMagnitude
}

Đôi khi khi bạn tạo UITableView bằng Xib hoặc Storyboard, câu trả lời không hoạt động. bạn có thể thử giải pháp thứ hai:

let headerView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
self.tableView.tableHeaderView = headerView

Hi vọng nó sẽ giúp ích cho bạn!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.