向 UICollectionViewCell 添加圆角和阴影

所以我已经通过各种职位添加第二视图添加阴影,但我仍然不能让它的工作,如果我想添加它在 UICollectionViewCell。我子类化了 UICollectionViewCell,下面是我的代码,我在单元格的内容视图中添加了各种 UI 元素,并在图层中添加了阴影:

[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]];

我想知道如何添加圆角和阴影的 UICollectionViewCell

111245 次浏览

设置单元格的 layer属性,而不是 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]];

你只需要(a)设置 cornerRadius和(b)设置 shadowPath为圆角直角,半径与 cornerRadius相同:

self.layer.cornerRadius = 10;
self.layer.shadowPath = [[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.layer.cornerRadius] CGPath];

这两种方法对我都不管用。如果您将所有子视图放入 UICollectionViewCell 内容视图中(您可能就是这样) ,那么您可以在单元格层上设置阴影,在 contentView 层上设置边框,以实现这两个结果。

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

如果有帮助的话: 下面是转弯的捷径:

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

单元格作为控制单元格的变量: 通常,您将在 override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell中使用它

Enjoy!

I had to make some slight changes for 斯威夫特:

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;

Swift 3版本:

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

这招对我很管用

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

这里的 Swift 4解决方案,更新到圆形的 每个弯角,而不仅仅是顶部弯角:

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

在创建 UICollectionViewCell时,可以在 UICollectionViewDataSource方法中设置阴影颜色、半径和偏移量

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

Mike Sabatini 的答案工作得很好,如果你直接在 CollectionView cellForItemAt 上配置单元格属性,但是如果你试图在自定义 UICollectionViewCell 子类的 awakeFromNib ()中设置它们,你会在设备上设置错误的 bezierPath,这与之前在 Storyboard (IB)中设置的宽度和高度不匹配。

对我来说,解决方案是在 UICollectionViewCell 的子类中创建一个 func,然后像这样从 cellForItemAt 调用它:

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()
}
}

在 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}
}

SWIFT 4.2

应该在自定义单元格或 cellForItemAt 中添加以下内容: 如果使用 cellForItemAt: 方法替换 self-> 单元格

        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

这将为您提供一个带有圆形边框和阴影的单元格。

这是我的答案,接近其他人,但我添加了一个角半径的图层,否则角将不会正确填充。而且,这对 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.

这是我对解决方案的看法。它与其他答案相似,但有一个关键区别。它不会创建依赖于视图边界的路径。任何时候,您创建一个路径的基础上的边界,并提供给层,您可能会遇到问题时,它的大小调整,并需要设置方法来更新的路径。

一个更简单的解决方案是避免使用任何依赖于边界的东西。

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

现在,当单元格大小发生变化时,视图 API 将在内部完成所有工作。

我使用以下方法来达到这种效果:

extension UICollectionViewCell {
/// Call this method from `prepareForReuse`, because the cell needs to be already rendered (and have a size) in order for this to work
func shadowDecorate(radius: CGFloat = 8,
shadowColor: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.3),
shadowOffset: CGSize = CGSize(width: 0, height: 1.0),
shadowRadius: CGFloat = 3,
shadowOpacity: Float = 1) {
contentView.layer.cornerRadius = radius
contentView.layer.borderWidth = 1
contentView.layer.borderColor = UIColor.clear.cgColor
contentView.layer.masksToBounds = true


layer.shadowColor = shadowColor.cgColor
layer.shadowOffset = shadowOffset
layer.shadowRadius = shadowRadius
layer.shadowOpacity = shadowOpacity
layer.masksToBounds = false
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath
layer.cornerRadius = radius
}
}

我发现了一个重要的事情: UICollectionViewCell 必须将背景色作为 clear颜色,以便使上述这些工作。

Swift 5 Xcode 13 iOS 14

首先将您的收藏配置如下:

self.collectionView.clipsToBounds = false

然后按如下方式配置您的单元格:

override func awakeFromNib() {
super.awakeFromNib()
    

self.configView()
}
    

private func configView() {
self.clipsToBounds = false
self.backgroundColor = .systemBackground
self.layer.cornerRadius = 10
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 0, height: 0.0)
self.layer.shadowRadius = 10
self.layer.shadowOpacity = 0.2
}

请注意这两个“ clipToBound = false”命令。

就这样。