Adding a rounded corner and shadow for a UICollectionViewCell

So, I already looked at various messages about adding a second view to add a shadow, but I still can’t get it working if I want to add it to a UICollectionViewCell . I have subclassed UICollectionViewCell , and here is my code where I add various user interface elements to the cell content view and add a 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 a rounded corner and shadow to a UICollectionViewCell .

+80
ios iphone uicollectionviewcell
Nov 22 '12 at 3:10
source share
14 answers

None of these solutions helped me. If you put all your subviews in the UICollectionViewCell content view, which you probably are, you can set the shadow on the cell layer and the border on the contentView 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 
+167
Aug 25 '14 at 19:44
source share
β€” -

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 
+26
Oct. 20 '16 at 18:04
source share

In case this helps: Here is a quick rounding of the corners:

 cell.layer.cornerRadius = 10 cell.layer.masksToBounds = true 

with the cell being the variable that controls the cell: often you'll use this in override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) β†’ UICollectionViewCell

Enjoy it!

+23
04 Oct '15 at 13:22
source share

Set layer attributes for the cell, not the 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]]; 
+14
Dec 04 '12 at 18:45
source share

Here is the Swift 4 solution, updated to round all corners, not just 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 
+10
May 16 '18 at 9:05
source share

You just need to (a) set cornerRadius and (b) set shadowPath as a rounded rectangle with the same radius as cornerRadius :

 self.layer.cornerRadius = 10; self.layer.shadowPath = [[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.layer.cornerRadius] CGPath]; 
+8
Dec 31 '13 at 18:05
source share

I had to make small 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; 
+6
Dec 15 '15 at 17:59
source share

SWIFT 4.2

You need to add this to your custom cell or cellForItemAt: if you use cellForItemAt: approach replace yourself -> 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 falling shadow.

+5
Apr 19 '19 at 12:29
source share

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 
+3
Oct 10 '17 at 6:09
source share

Mike Sabatini's answer works fine if you set cell properties directly in collectionView cellForItemAt, but if you try to set them in awakeFromNib () of a custom subclass of UICollectionViewCell, you will have the wrong bezierPath installed on devices that don't work. does not match the width and height previously set in the storyboard (IB).

The solution for me was to create a function inside a subclass of UICollectionViewCell and call it from cellForItemAt as follows:

 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 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} } 
+2
Oct 26 '18 at 4:29
source share

You can set the shadow color, radius and offset in the UICollectionViewDataSource method when 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 
+1
Jun 27 '18 at 13:00
source share

If you are loading a cell from xib, then awakeFromNib is where you put the code.

 class MyCollectionViewCell: UICollectionViewCell { override func awakeFromNib() { layer.cornerRadius = 7 layer.masksToBounds = true } } 
0
Jun 08 '19 at 18:00
source share

Here is my answer, close to the others, but I am adding an angular radius to the layer, otherwise the corners will not fill correctly. In addition, it makes a small slight extension to the 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:) data source as soon as you remove your cell from the queue.

0
Jul 13 '19 at 20:13
source share

Here is my solution. This is similar to the other answers, with one key difference. This does not create a path that depends on the boundaries of the view. Each time you create a path based on borders and provide it with a layer, you may run into problems when changing it, and you need to set up methods to update the path.

A simpler solution is to avoid using anything that depends on boundaries.

 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 rounded shape self.layer.cornerRadius = radius 

Now, when the cell size ever changes, the presentation API will do all the work internally.

0
Jul 23 '19 at 17:50
source share



All Articles