Table view cell only masks correctly after scrolling off and then back on

后端 未结 6 1610
無奈伤痛
無奈伤痛 2021-02-04 06:08

I\'m modifying a table view cell during a call to tableView:cellForIndexPath, but the modifications do not appear until the cell is scrolled off and then back on. I

6条回答
  •  粉色の甜心
    2021-02-04 07:00

    I can't reproduce your issue on iOS 9.2, as your code is working fine for me.

    If you are supporting older versions, I believe the issue you are facing is related to the cell's initial width not corresponding to the tableView's width. Before a cell is laid out, its initial width was based on its Storyboard width (which differs from the actual screen width).

    What happens is that your shapeLayer mask starts out out with the wrong bounds, so the mask won't appear correctly until the cell is reused. At that point, since the cell has been laid out, its width is now correct, the new mask's bounds are correct, and the proper effect is achieved.

    While you can try to perform layout in cellForRowAtIndexPath, it involves a bit more code to handle edge cases like initial cell width issues.

    It's a lot easier to apply the mask after the cell has been laid out, such as technerd suggested in their answer.

    That's the explanation for the problem.

    The changes involve masking the cell to achieve rounded bottom corners. If I set the corner radius instead (i.e. cell.layer.cornerRadius = ...), which rounds all the corners, I don't see the problem.

    Since that doesn't involve adding a shape layer with a specific frame size, you won't run into an issue. The cell's layer will be the proper size when rendering occurs, so the rounded corners will show up correctly.

    How this had needed to be handled

    I don't know what version of iOS you need to support (since this issue has been fixed in recent versions), but here is one of the ways to work around the issue where the cell was not initially laid out properly until you scrolled off-screen, then back on-screen.

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    
        // Workaround for visible cells not laid out properly since their layout was
        // based on a different (initial) width from the tableView.
    
        CGRect rect = cell.frame;
        rect.size.width = CGRectGetWidth(tableView.bounds);
        cell.frame = rect;
    
        ... configure cell
    
        [cell setNeedsUpdateConstraints];
        [cell updateConstraintsIfNeeded];
    
        return cell;
    }
    

    You may be able to get away with setNeedsLayout; layoutIfNeeded. In my app, I had needed the constraints to be updated for other reasons.

提交回复
热议问题