Reputation: 16725
I have a UICollectionView
in a UIViewController
. I use the following extension to configure the UICollectionViewCell
s to have rounded corners and shadows:
extension UICollectionViewCell {
func configureCell() {
self.contentView.layer.cornerRadius = 5.0
self.contentView.layer.borderWidth = 1.0
self.contentView.layer.borderColor = UIColor.clear.cgColor
self.contentView.backgroundColor = UIColor.white
self.contentView.layer.masksToBounds = true
self.layer.shadowColor = UIColor.lightGray.cgColor
self.layer.shadowOffset = CGSize.zero
self.layer.shadowRadius = 2.0
self.layer.shadowOpacity = 1.0
self.layer.masksToBounds = false
self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.contentView.layer.cornerRadius).cgPath
}
}
When the UICollectionView
is initially drawn, rounded corners and shadows are drawn on the cells. However, when I move the cells corners start disappearing, but the shadows remain. I figured I just need to update the cells, so I added this to moveItemAt
:
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
[collectionView.cellForItem(at: sourceIndexPath), collectionView.cellForItem(at: destinationIndexPath)].forEach({$0?.configureCell()})
}
That didn't work, so I tried this:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.visibleCells.forEach({$0.configureCell()})
}
Same result...rounded corners disappear, but shadows remain.
I welcome suggestions on how to keep corners rounded when UICollectionViewCells
are moved. Thank you for reading.
Update:
Upon further tinkering, I've discovered any time the cells are clicked subsequent to the initial view loading, the rounded corners go square when the cell is clicked. So I tried this:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.cellForItem(at: indexPath)?.configureCell()
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
collectionView.cellForItem(at: indexPath)?.configureCell()
}
Upvotes: 2
Views: 2723
Reputation: 16725
I determined the problem was in my extension. I'm not 100% sure why it initially draws correctly and doesn't update, but I needed to take out the contentView
reference and go straight to the layer
.
I also took out all the references to configureCell()
calls from the other methods. It works as desired. Here's what it looks like.
extension UICollectionViewCell {
func configureCell() {
self.layer.cornerRadius = 5.0
self.layer.borderWidth = 1.0
self.layer.borderColor = UIColor.clear.cgColor
self.backgroundColor = UIColor.white
self.layer.masksToBounds = true
self.layer.shadowColor = UIColor.lightGray.cgColor
self.layer.shadowOffset = CGSize.zero
self.layer.shadowRadius = 2.0
self.layer.shadowOpacity = 1.0
self.layer.masksToBounds = false
self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.contentView.layer.cornerRadius).cgPath
}
}
Upvotes: 3
Reputation: 4373
My test are showing that it is working and I am not having any of your issues. I wonder where you are doing the initial configuration of the cell. My guess is that it is not in cellForItem but there may be something else. Here is my complete code and the collection view is loaded from storyboard with an identifier of "testCell"
import UIKit
class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
collectionView.delegate = self
collectionView.dataSource = self
//horizontal
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//or cast to your cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "testCell", for: indexPath)
//if you are dynamically sizing the cells I would call this last
cell.configureCell()
cell.layer.shouldRasterize = true
cell.layer.rasterizationScale = UIScreen.main.scale
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 100, height: 100)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
if let ourCell = cell{
let highlightTest = UIView(frame: ourCell.bounds)
highlightTest.layer.cornerRadius = ourCell.contentView.layer.cornerRadius
highlightTest.backgroundColor = UIColor.lightGray
highlightTest.layer.opacity = 0.4
highlightTest.alpha = 0
ourCell.contentView.addSubview(highlightTest)
UIView.animate(withDuration: 0.3, delay: 0, options: .autoreverse, animations: {
highlightTest.alpha = 1
}, completion: {
finished in
highlightTest.removeFromSuperview()
})
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
}
}
extension UICollectionViewCell {
func configureCell() {
self.layer.cornerRadius = 5.0
self.layer.borderWidth = 1.0
self.layer.borderColor = UIColor.clear.cgColor
self.contentView.backgroundColor = UIColor.white
self.contentView.layer.masksToBounds = true
self.layer.shadowColor = UIColor.lightGray.cgColor
self.layer.shadowOffset = CGSize.zero
self.layer.shadowRadius = 2.0
self.layer.shadowOpacity = 1.0
self.layer.masksToBounds = false
self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.contentView.layer.cornerRadius).cgPath
}
}
Upvotes: 0