向UICollectionViewCell添加圆角和阴影


104

因此,我已经在添加第二视图以添加阴影的过程中经历过各种讨论,但是如果要在中添加阴影,我仍然无法使它正常工作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


我认为您需要改善自己的问题才能让他人理解。您的要求真的很混乱
Dinesh Raja 2012年

好的更新,我只想知道如何向UICollectionViewCell添加圆角和阴影
Vincent Yiu

暂且不谈-使用shadowRadius或setShadowPath,不要做任何事,因为在此情况下它们本质上是同一条指令(所有圆角)。如果您想将更复杂的形状或圆角不应用于所有角,则必须使用阴影路径。
2014年

Answers:


194

这些解决方案都不适合我。如果将所有子视图都放置在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;

斯威夫特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

9
在我添加之后,这对我来说效果很好cell.layer.backgroundColor = [UIColor clearColor].CGColor;
2014年

2
知道为什么这仅能使我圆满完成吗?
user3344977

@ user3344977也许底部被剪裁了?如在角落是圆形的,但在单元格的可见部分下方
CoderNinja

5
我发现这是我的顶角,而不是我的底角。
fatuhoku 2015年

2
当您选择/取消选择/移动单元格时,如何使角落保持圆角?在最初正确绘制单元格时,只要在单元格上呼吸,我的角落就会成直角。
阿德里安

32

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

我需要在每个单元格的右上角和底部添加阴影效果,并且上述代码的工作方式是,用阴影颜色填充该单元格……
Joe Sene

25

如果有帮助的话:这是快速解决问题的方法:

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

单元格是控制单元格的变量:通常,您将在 override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell

请享用!


18

在这里,斯威夫特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

1
也可以迅速地在4,2中工作
-ShadeToD

2
我一直在寻找解决方案...感谢年轻的Massimo:'D
Massimo Polimeni

16

设置单元的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]];

2
这似乎对我不起作用。我对uitableviewcell使用了类似的代码,但是在collectionviewcell中似乎不起作用。奇怪的是,相同的代码在cv单元中无法正常工作。
杰森

我上述评论的更新。我发现UICollectionViewCells似乎使用了与UITableViewCells不同的阴影偏移。如果没有看到阴影,请尝试更改偏移量(增加Y值对我有帮助)。
杰森

14

SWIFT 4.2

应该将其添加到您的自定义单元格或cellForItemAt:如果使用cellForItemAt:方法替代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

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


13

这是我的答案,与其他答案很接近,但是我在图层上添加了一个圆角半径,否则将无法正确填充这些圆角。此外,这在上做了一个不错的扩展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
}

}

collectionView(_:cellForItemAt:)出队后,您可以在数据源中调用它。


8

您只需要将(a)设置为cornerRadius(b)并将其设置shadowPath为具有与以下元素相同的半径的圆角矩形cornerRadius

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

2
知道为什么这只会使我的心烦吗?
user3344977

听起来好像您要四舍五入的任何层都被某些东西遮盖了。没有细节,没有比这更进一步的了。
蒂莫西·穆斯

嗨,蒂姆,我只是问了这个问题。我觉得您很快就能得到它。是因为我在单元的底部/“下面”仅具有阴影吗?stackoverflow.com/q/27929735/3344977
user3344977 2015年

6

我必须对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;

3

如果直接在collectionView cellForItemAt上配置单元格属性,Mike Sabatini的答案就可以很好地工作,但是如果尝试在自定义UICollectionViewCell子类的awakeFromNib()中设置它们,则会在设置了该属性的设备上以错误的bezierPath结尾与先前在情节提要(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}
 }

3

这个为我工作

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

我使用以下方法来实现这种效果:

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

2

您可以在创建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

2

这是我对解决方案的看法。它与其他答案类似,但有一个主要区别。它不会创建依赖于视图范围的路径。每当您基于边界创建路径并将其提供给图层时,在调整大小时都会遇到问题,并且需要设置方法来更新路径。

一个更简单的解决方案是避免使用任何与范围相关的东西。

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就会在内部完成所有工作。


我认为这是最干净的答案。喜欢保持半径同步的想法。
Kirill Kudaev

2

我发现了一件重要的事情:UICollectionViewCell必须具有backgroundColor作为clear颜色,以使上述功能起作用。


这对于实现不遮挡阴影非常重要!不要忽略这个答案,非常感谢,伙计!
DennyDog
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.