UICollectionViewCell with rounded corners AND drop

2020-02-17 09:54发布

I want my UICollectionViewCells to have rounded corners and drop shadows but I have run into a problem where it seems I can only have one or the other, but not both.

To just round the corners I use this code in the initialization of the cell:

CALayer *layer = [self layer];
[layer setCornerRadius:4];
[layer setRasterizationScale:[[UIScreen mainScreen] scale]];
[layer setShouldRasterize:YES];

To just add a drop shadow I use this code in the initialization of the cell:

CALayer *layer = [self layer];
[layer setMasksToBounds:NO];
[layer setRasterizationScale:[[UIScreen mainScreen] scale]];
[layer setShouldRasterize:YES];
[layer setShadowColor:[[UIColor blackColor] CGColor]];
[layer setShadowOffset:CGSizeMake(0.0f,0.5f)];
[layer setShadowRadius:8.0f];
[layer setShadowOpacity:0.2f];
[layer setShadowPath:[[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:layer.cornerRadius] CGPath]];

To try and have rounded corners and a drop shadow I use this code in the initialization of the cell:

CALayer *layer = [self layer];
[layer setMasksToBounds:NO];
[layer setCornerRadius:4];
[layer setRasterizationScale:[[UIScreen mainScreen] scale]];
[layer setShouldRasterize:YES];
[layer setShadowColor:[[UIColor blackColor] CGColor]];
[layer setShadowOffset:CGSizeMake(0.0f,0.5f)];
[layer setShadowRadius:8.0f];
[layer setShadowOpacity:0.2f];
[layer setShadowPath:[[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:layer.cornerRadius] CGPath]];

but this results in the drop shadow only.

Is this a bug or am I doing something wrong?

5条回答
做自己的国王
2楼-- · 2020-02-17 10:16

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 lightGrayColor].CGColor;
cell.layer.shadowOffset = CGSizeMake(0, 2.0f);
cell.layer.shadowRadius = 2.0f;
cell.layer.shadowOpacity = 1.0f;
cell.layer.masksToBounds = NO;
cell.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:cell.contentView.layer.cornerRadius].CGPath;

Swift 4.0

cell.contentView.layer.cornerRadius = 2.0
cell.contentView.layer.borderWidth = 1.0
cell.contentView.layer.borderColor = UIColor.clear.cgColor
cell.contentView.layer.masksToBounds = true
cell.layer.shadowColor = UIColor.lightGray.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
查看更多
Anthone
3楼-- · 2020-02-17 10:21

There is tricky moment. Cutting corners and dropping shadow is mutually exclusive function in one layer. Dropping shadow is frame extension process, but corners is the process of masking to bounds.

Solution is in function separation. I recommend setup shadow for the cell layer, but cut corners for contentView layer of that cell.

查看更多
地球回转人心会变
4楼-- · 2020-02-17 10:23

I think I ran into a similar issue. My problem was that clipping in my subviews of the UICollectionViewCell didn't work properly with shadows and rounded borders. The exact same code worked just fine before when I had that view (as a standard UIView subclass though) in a UIScrollView.

So long story short, I moved all this setup from the initWithCoder to a later place after getting it from -dequeueReusableCellWithReuseIdentifier:forIndexPath:. Solved the problem for me. Seems like UICollectionViews are doing something I wouldn't expect to their cells' layers at some point?

查看更多
▲ chillily
5楼-- · 2020-02-17 10:32

If you are using a subclass to make the collection just make sure you do the following.

CALayer *layer = [self layer];
[layer setCornerRadius:_cornerRadius];
[layer setRasterizationScale:[[UIScreen mainScreen] scale]];
[layer setShouldRasterize:YES];
[layer setShadowColor:[[UIColor blackColor] CGColor]];
[layer setShadowOffset:CGSizeMake(0.0,4.0)];
[layer setShadowRadius:6.0f];
[layer setShadowOpacity:0.25];
[layer setShadowPath:[[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:layer.cornerRadius] CGPath]];

self.contentView.layer.cornerRadius = _cornerRadius;
self.contentView.layer.borderWidth= _borderWidth;
self.contentView.layer.borderColor = _borderColor.CGColor;
self.contentView.backgroundColor = [UIColor whiteColor];
self.backgroundColor = [UIColor clearColor];

works like a charm.

查看更多
Bombasti
6楼-- · 2020-02-17 10:34

Works for me great:

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        ...
        cell.layer.masksToBounds = YES;
        cell.layer.cornerRadius = 6;
        ...
        return cell;
    }
查看更多
登录 后发表回答