Swapnil Dhanwal
Swapnil Dhanwal

Reputation: 399

Shadow not conforming to the shape of view in UITableViewCell

I have a table view in which I'm trying to add card-style cells. To achieve this, I added a UIView (paddingView) onto the cell's content view, sized slightly smaller than it. Now to create the shadow effect, I am using the following code:

    let path = UIBezierPath(rect: cell.paddingView.bounds)
    cell.paddingView.layer.shadowPath = path.CGPath
    cell.paddingView.layer.shadowOffset = CGSizeMake(0.5, 0.5)
    cell.paddingView.layer.shadowOpacity = 0.4

The problem arises when the table view is first loaded. The shadow under each cell appears as follows:

enter image description here

This is how it looks when I scroll it once How can I ensure that the shadow effect is proper, and not like the above image?

enter image description here

Upvotes: 4

Views: 2437

Answers (4)

Vitalii
Vitalii

Reputation: 4447

Had exactly the same issue with shadow when a new cell was added to the table offscreen. This sounded like wrong shadowPath because the cell had slightly incorrect bounds when it appeared offscreen.

Found two possible solutions that worked in my case:

Solution 1: changing tableView.reloadData() to

tableView.reloadData()
tableView.setNeedsLayout()
tableView.layoutIfNeeded()
tableView.reloadData()

Solution 2: not setting the shadowPath at all, I mean simply removing this from the example code would work:

// cell.paddingView.layer.shadowPath = path.CGPath

The shadowPath is mostly needed to improve performance. It will be calculated dynamically if not set.

Upvotes: 0

Anny
Anny

Reputation: 499

try this

    cell.vwMain.layer.shadowOffset = CGSize(width: 0, height: 5)
    cell.vwMain.layer.shadowOpacity = 0.05
    cell.vwMain.layer.shadowRadius = 5

or

    cell.layer.shadowOffset = CGSizeMake(0.0, 5);
    cell.layer.shadowOpacity = 0.2;
    cell.layer.shadowRadius = 5;

This will give you a card style effect

Upvotes: 0

student swift
student swift

Reputation: 29

It seems that the problem is that there are differences between the frame in storyboard and the frame in runtime.

Therefore when you rolled it worked out. Because the layout was refreshed.

Try adding this code into the function cellForRowAtIndexPath:

cell.setNeedsLayout()

cell.layoutIfNeeded()

Upvotes: 1

user4151918
user4151918

Reputation:

The wrong shadow width issue that you are seeing at first load is related to using the bounds of the paddingView before the cell's subviews are laid out.

When a cell is instantiated, it can start out with the wrong initial width (which is based on the storyboard), instead of being initially set to the actual width of the tableView.

The reason why the issue goes away after scrolling off- then on-screen is that the reused cell has the right paddingView bounds width, so the shadow now appears correct.

This was a common issue for self-sizing cells not initially being laid out properly, until the table was (scrolled or) reloaded. There are several workarounds going back almost two years, that vary from reloading the table, to forcing a layout pass.

Both ensure that the cell initial width is correct at first use.

If you're supporting older versions of iOS, this issue can crop up. I don't recall which exact version of iOS fixed it for good, but I haven't had to work around this issue in quite a while.

Upvotes: 4

Related Questions