So I already went through various posts on adding 2nd view for adding shadow, but I still cannot get it to work if I want to add it in UICollectionViewCell. I subclassed UICollectionViewCell, and here is my code where I add various UI elements to the cell's content view and adding shadow to the layer:
[self.contentView setBackgroundColor:[UIColor whiteColor]];
self.layer.masksToBounds = NO;
self.layer.shadowOffset = CGSizeMake(0, 1);
self.layer.shadowRadius = 1.0;
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOpacity = 0.5;
[self.layer setShadowPath:[[UIBezierPath bezierPathWithRect:self.bounds] CGPath]];
I would like to know how to add rounded corner and shadow to UICollectionViewCell.
Neither of these solutions worked for me. If you place all your subviews into the UICollectionViewCell content view, which you probably are, you can set the shadow on the cell's layer and the border on the contentView's layer to achieve both results.
cell.contentView.layer.cornerRadius = 2.0f;
cell.contentView.layer.borderWidth = 1.0f;
cell.contentView.layer.borderColor = [UIColor clearColor].CGColor;
cell.contentView.layer.masksToBounds = YES;
cell.layer.shadowColor = [UIColor blackColor].CGColor;
cell.layer.shadowOffset = CGSizeMake(0, 2.0f);
cell.layer.shadowRadius = 2.0f;
cell.layer.shadowOpacity = 0.5f;
cell.layer.masksToBounds = NO;
cell.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:cell.contentView.layer.cornerRadius].CGPath;
Swift 3.0
self.contentView.layer.cornerRadius = 2.0
self.contentView.layer.borderWidth = 1.0
self.contentView.layer.borderColor = UIColor.clear.cgColor
self.contentView.layer.masksToBounds = true
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 0, height: 2.0)
self.layer.shadowRadius = 2.0
self.layer.shadowOpacity = 0.5
self.layer.masksToBounds = false
self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.contentView.layer.cornerRadius).cgPath
Swift 3 version:
cell.contentView.layer.cornerRadius = 10
cell.contentView.layer.borderWidth = 1.0
cell.contentView.layer.borderColor = UIColor.clear.cgColor
cell.contentView.layer.masksToBounds = true
cell.layer.shadowColor = UIColor.gray.cgColor
cell.layer.shadowOffset = CGSize(width: 0, height: 2.0)
cell.layer.shadowRadius = 2.0
cell.layer.shadowOpacity = 1.0
cell.layer.masksToBounds = false
cell.layer.shadowPath = UIBezierPath(roundedRect:cell.bounds, cornerRadius:cell.contentView.layer.cornerRadius).cgPath
In case it helps: Here is the swift for rounding the corners:
cell.layer.cornerRadius = 10
cell.layer.masksToBounds = true
with cell being a variable controlling the cell: often, you will use this in override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
Enjoy!
Set the layer attributes for the cell, not contentView.
CALayer * layer = [cell layer];
[layer setShadowOffset:CGSizeMake(0, 2)];
[layer setShadowRadius:1.0];
[layer setShadowColor:[UIColor redColor].CGColor] ;
[layer setShadowOpacity:0.5];
[layer setShadowPath:[[UIBezierPath bezierPathWithRect:cell.bounds] CGPath]];
Here the Swift 4 solution, updated to round every corners and not only the top corners:
contentView.layer.cornerRadius = 6.0
contentView.layer.borderWidth = 1.0
contentView.layer.borderColor = UIColor.clear.cgColor
contentView.layer.masksToBounds = true
layer.shadowColor = UIColor.lightGray.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2.0)
layer.shadowRadius = 6.0
layer.shadowOpacity = 1.0
layer.masksToBounds = false
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: contentView.layer.cornerRadius).cgPath
layer.backgroundColor = UIColor.clear.cgColor
You simply need to (a) set cornerRadius and (b) set shadowPath to be a rounded rect with the same radius as cornerRadius:
self.layer.cornerRadius = 10;
self.layer.shadowPath = [[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.layer.cornerRadius] CGPath];
SWIFT 4.2
One should add this in your custom cell or cellForItemAt: If you are using the cellForItemAt: approach substitute self -> cell
self.layer.cornerRadius = 10
self.layer.borderWidth = 1.0
self.layer.borderColor = UIColor.lightGray.cgColor
self.layer.backgroundColor = UIColor.white.cgColor
self.layer.shadowColor = UIColor.gray.cgColor
self.layer.shadowOffset = CGSize(width: 2.0, height: 4.0)
self.layer.shadowRadius = 2.0
self.layer.shadowOpacity = 1.0
self.layer.masksToBounds = false
This will give you a cell with a rounded border and a drop shadow.
I had to make some slight changes for Swift:
cell.contentView.layer.cornerRadius = 2.0;
cell.contentView.layer.borderWidth = 1.0;
cell.contentView.layer.borderColor = UIColor.clearColor().CGColor;
cell.contentView.layer.masksToBounds = true;
cell.layer.shadowColor = UIColor.grayColor().CGColor;
cell.layer.shadowOffset = CGSizeMake(0, 2.0);
cell.layer.shadowRadius = 2.0;
cell.layer.shadowOpacity = 1.0;
cell.layer.masksToBounds = false;
cell.layer.shadowPath = UIBezierPath(roundedRect:cell.bounds, cornerRadius:cell.contentView.layer.cornerRadius).CGPath;
This one worked for me
cell.contentView.layer.cornerRadius = 5.0
cell.contentView.layer.borderColor = UIColor.gray.withAlphaComponent(0.5).cgColor
cell.contentView.layer.borderWidth = 0.5
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.darkGray.cgColor
border.frame = CGRect(x: 0, y: cell.contentView.frame.size.height - width, width: cell.contentView.frame.size.width, height: cell.contentView.frame.size.height)
border.borderWidth = width
cell.contentView.layer.addSublayer(border)
cell.contentView.layer.masksToBounds = true
cell.contentView.clipsToBounds = true
The answer of Mike Sabatini works fine, if you configure the cell properties directly on the collectionView cellForItemAt, but if you try to set them in awakeFromNib() of a custom UICollectionViewCell subclass, you will end with a wrong bezierPath set on the devices that doesn't match the width and height previously set in your Storyboard (IB).
Solution for me was create a func inside the subclass of UICollectionViewCell and calling it from the cellForItemAt like this:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellID", for: indexPath) as? CustomCollectionViewCell{
cell.configure())
return cell
}
else {
return UICollectionViewCell()
}
}
And on the CustomCollectionViewCell.swift :
class CustomCollectionViewCell: UICollectionViewCell{
func configure() {
contentView.layer.cornerRadius = 20
contentView.layer.borderWidth = 1.0
contentView.layer.borderColor = UIColor.clear.cgColor
contentView.layer.masksToBounds = true
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2.0)
layer.shadowRadius = 2.0
layer.shadowOpacity = 0.5
layer.masksToBounds = false
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: contentView.layer.cornerRadius).cgPath}
}
You can set shadow color, radius and offset in UICollectionViewDataSource method while creating a UICollectionViewCell
cell.layer.shadowColor = UIColor.gray.cgColor
cell.layer.shadowOffset = CGSize(width: 0, height: 2.0)
cell.layer.shadowRadius = 1.0
cell.layer.shadowOpacity = 0.5
cell.layer.masksToBounds = false
If you're loading the cell from a xib, then awakeFromNib is where to put the code.
class MyCollectionViewCell: UICollectionViewCell {
override func awakeFromNib() {
layer.cornerRadius = 7
layer.masksToBounds = true
}
}
Here's my answer, close to the others, but I add a corner radius to the layer otherwise the corners won't fill in correctly. Also, this makes a nice little extension on UICollectionViewCell.
extension UICollectionViewCell {
func shadowDecorate() {
let radius: CGFloat = 10
contentView.layer.cornerRadius = radius
contentView.layer.borderWidth = 1
contentView.layer.borderColor = UIColor.clear.cgColor
contentView.layer.masksToBounds = true
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 1.0)
layer.shadowRadius = 2.0
layer.shadowOpacity = 0.5
layer.masksToBounds = false
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath
layer.cornerRadius = radius
}
}
You can call it in collectionView(_:cellForItemAt:) of the datasource once you dequeue your cell.
Here's my take on the solution. It's similar to other answers, with one key difference. It doesn't create a path that's dependent on the bounds of the view. Anytime you create a path based on the bounds and provide it to the layer you can run into issues when it's resizing, and need to setup methods to update the path.
A simpler solution is to avoid using anything that is bounds dependent.
let radius: CGFloat = 10
self.contentView.layer.cornerRadius = radius
// Always mask the inside view
self.contentView.layer.masksToBounds = true
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 0, height: 1.0)
self.layer.shadowRadius = 3.0
self.layer.shadowOpacity = 0.5
// Never mask the shadow as it falls outside the view
self.layer.masksToBounds = false
// Matching the contentView radius here will keep the shadow
// in sync with the contentView's rounded shape
self.layer.cornerRadius = radius
Now when ever the cells size change the view API will do all the work internally.
来源:https://stackoverflow.com/questions/13505379/adding-rounded-corner-and-drop-shadow-to-uicollectionviewcell