Dipika
Dipika

Reputation: 1127

Grouped table view with shadow

I want to achieve a grouped tableView along with shadow same as in the below image.

Grouped tableView cells

To archive rounded corners along with shadow, I have simply added a separate UIView behind my main view and pinned it with main view from all side, like this

Applying shadow on shadow view and depending on cell's index rounded corners via masking on main view. And this way successfully achieving masked rounded corners with shadow.

But the shadows of cells are overlapping:

In order to resolve this, the top cell should have shadow on the top, right and left, the middle cell only right and left side and the bottom cell should have shadow on right, left and bottom side.

Upvotes: 0

Views: 901

Answers (1)

Harry J
Harry J

Reputation: 1956

I messed around with this for ages, and eventually altered some Objc code to have your desired result.

I never had the will to make it work for single cells too. Always a few bugs. However for two or more cells, use this extension on the cell itself and not the contentView.

Inside cells layoutSubviews

backgroundView = UIView(frame: contentView.frame)
backgroundView?.clipsToBounds = false
backgroundView?.backgroundColor = .clear

addShadowToCellInTableView(lastIndex: lastIndex, atIndexPath: indexPath)
public extension UITableViewCell {
    /** adds a drop shadow to the background view of the (grouped) cell */
    func addShadowToCellInTableView(lastIndex: Int, atIndexPath indexPath: IndexPath!) {
        let isFirstRow: Bool = indexPath.row == 0
        let isLastRow: Bool = (indexPath.row == lastIndex - 1)

        guard let backgroundView = self.backgroundView else { return }

        let backBounds = backgroundView.bounds
        // the shadow rect determines the area in which the shadow gets drawn
        var shadowRect: CGRect = backBounds.insetBy(dx: 0, dy: -10)
        if isFirstRow {
            shadowRect.origin.y += 10
        } else if isLastRow {
            shadowRect.size.height -= 10
        }

        // the mask rect ensures that the shadow doesn't bleed into other table cells
        var maskRect: CGRect = backBounds.insetBy(dx: -20, dy: 0)
        if isFirstRow {
            maskRect.origin.y -= 10
            maskRect.size.height += 10
        } else if isLastRow {
            maskRect.size.height += 10
        }

        // now configure the background view layer with the shadow
        let layer: CALayer = backgroundView.layer
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 0)
        layer.shadowRadius = 4
        layer.shadowOpacity = 0.23
        layer.shadowPath = UIBezierPath(rect: shadowRect).cgPath
        layer.masksToBounds = false

        // and finally add the shadow mask
        let maskLayer = CAShapeLayer()
        maskLayer.path = UIBezierPath(rect: maskRect).cgPath
        layer.mask = maskLayer
    }

    func addShadowToSingleCell() {
        layer.shadowOpacity = 0.23
        layer.shadowRadius = 4
        layer.shadowOffset = CGSize(width: 0, height: 0)
        layer.shadowColor = UIColor.black.cgColor

        layer.shadowPath = UIBezierPath(roundedRect: contentView.frame,
                                        cornerRadius: contentView.layer.cornerRadius).cgPath
    }
}

Upvotes: 0

Related Questions