How to make UICollectionViewCells have rounded cor

2019-08-29 12:02发布

问题:

I've seen some other answers to similar questions, but none of the solutions have worked for me, even with some tweaking.

As the title suggests, I would like my UICollectionViewCells to have rounded corners and drop shadows (or shadows on all sides except the top). What I have done so far is to add two views to my UICollectionViewCell - mainView, which displays the cell's necessary content and has rounded corners, and shadowView, which has the shadow. Neither view is a subview of the other, they exist together in the same cell. They are both the exact same dimensions, and mainView is obviously displayed on top of shadowView. Here is my current code implementation:

let mainView = cell.viewWithTag(1003) as! UIView       
mainView.layer.cornerRadius = 10.0
mainView.layer.borderWidth = 1.0
mainView.layer.borderColor = UIColor.clear.cgColor
mainView.layer.masksToBounds = true

let shadowView = cell.viewWithTag(1002) as! UIView
shadowView.layer.shadowColor = UIColor.black.cgColor
shadowView.layer.shadowOffset = CGSize(width: 0, height: 2.0)
shadowView.layer.shadowRadius = 2.0
shadowView.layer.shadowOpacity = 0.5
shadowView.layer.masksToBounds = false
shadowView.layer.shadowPath = UIBezierPath(roundedRect: shadowView.bounds, cornerRadius: mainView.layer.cornerRadius).cgPath

Here is what this code produces: One would think that mainView's corners aren't rounded enough, and that the shadow isn't big enough.

However, upon removing shadowView and setting the UICollectionView's background to black, you can see that mainView's corners are actually quite rounded:

So this implies that the issue is with shadowView's shadow size. However, I have tried increasing the shadow offsets and the the shadow radius, which did nothing. Most changes either produced a very thick shadow around mainView, decreased mainView's rounding even more, or did nothing.

Here is an image of the relevant UITableViewCell's view hierarchy in the Storyboard:

回答1:

Here is the Cell code:

class CollectionViewCell: UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)


        layer.shadowColor = UIColor.lightGray.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 2.0)
        layer.shadowRadius = 5.0
        layer.shadowOpacity = 1.0
        layer.masksToBounds = false
        layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: contentView.layer.cornerRadius).cgPath
        layer.backgroundColor = UIColor.clear.cgColor

        contentView.layer.masksToBounds = true
        layer.cornerRadius = 10
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Here is the usage code:

import UIKit

private let reuseIdentifier = "Cell"

class CollectionViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.collectionView!.register(CollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
        (self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize = CGSize(width: 100, height: 100)
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
        cell.backgroundColor = .white
        return cell
    }
}

Here is the result:



回答2:

Update

Thanks for the chat on Hangouts. I downloaded your code and mainView and shadowView was nil.

  • I noticed that you're not comfortable with CollectionViewCells.

With that being said. I'm more than happy to introduce our friend Runtime Attributes

Without touching your code. Select a view and add your runtime attribute key and set the value.

Output:

Go ahead, and do the work for the shadow and the rest.


The mainView is rounded, but the shadowView is taking all the credit.

You need to enable clipsToBounds on both views:

mainView.clipsToBounds = true