UITableView - How to keep table rows fixed as user scrolls

后端 未结 3 2027
隐瞒了意图╮
隐瞒了意图╮ 2020-12-24 15:29

I\'d like to be able to fix the position of certain rows in a UITableView as the user scrolls.

Specifically, I have a table whereby certain rows are \"headers\" for

相关标签:
3条回答
  • 2020-12-24 15:52

    I've been playing about with this and I've come up with a simple solution.

    First, we add a single UITableViewCell property to the controller. This should be initialize such that looks exactly like the row cells that we'll use to create the false section headers.

    Next, we intercept scrolling of the table view

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        // Add some logic here to determine the section header. For example, use 
        // indexPathsForVisibleRows to get the visible index paths, from which you 
        // should be able to get the table view row that corresponds to the current 
        // section header. How this works will be implementation dependent.
        //
        // If the current section header has changed since the pervious scroll request 
        // (because a new one should now be at the top of the screen) then you should
        // update the contents.
    
        IndexPath *indexPathOfCurrentHeaderCell = ... // Depends on implementation
        UITableViewCell *headerCell = [self.tableView cellForRowAtIndexPath:indexPathOfCurrentHeaderCell];
    
        // If it exists then it's on screen. Hide our false header
    
        if (headerCell)
            self.cellHeader.hidden = true;
    
        // If it doesn't exist (not on screen) or if it's partially scrolled off the top,
        // position our false header at the top of the screen
    
        if (!headerCell || headerCell.frame.origin.y < self.tableView.contentOffset.y )
        {
            self.cellHeader.hidden = NO;
            self.cellHeader.frame = CGRectMake(0, self.tableView.contentOffset.y, self.cellHeader.frame.size.width, self.cellHeader.frame.size.height);
        }
    
        // Make sure it's on top of all other cells
    
        [self.tableView bringSubviewToFront:self.cellHeader];
    }
    

    Finally, we need to intercept actions on that cell and do the right thing...

    0 讨论(0)
  • 2020-12-24 15:58

    That's the default behavior for section headers in plain UITableView instances. If you want to create a custom header, implement the tableView:viewForHeaderInSection: method in your table view delegate and return the view for your header.

    Although you will have to manage sections and rows instead of just rows.

    0 讨论(0)
  • 2020-12-24 16:02

    Swift 5 solution

    var header: UIView?
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(indexPath: indexPath) as UITableViewCell
        header = cell.contentView
        return cell
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let headerCell = tableView.cellForRow(at: IndexPath(row: 0, section: 0))
        guard headerCell == nil || (headerCell!.frame.origin.y < self.tableView.contentOffset.y + headerCell!.frame.height/2) else {
            header?.isHidden = true
            return
        }
        guard let hdr = header else { return }
        hdr.isHidden = false
        hdr.frame = CGRect(x: 0, y: tableView.contentOffset.y, width: hdr.frame.size.width, height: hdr.frame.size.height)
        if !tableView.subviews.contains(hdr) {
            tableView.addSubview(hdr)
        }
        tableView.bringSubviewToFront(hdr)
    }
    
    0 讨论(0)
提交回复
热议问题