การเพิ่มมุมโค้งมนและเงาตกใน UICollectionViewCell


107

ดังนั้นผมแล้วเดินผ่านโพสต์ต่างๆเกี่ยวกับการเพิ่มมุมมองที่ 2 สำหรับการเพิ่มเงา 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

อัปเดตแล้วฉันแค่อยากรู้วิธีเพิ่มมุมโค้งมนและเงาให้กับ UICollectionViewCell
Vincent Yiu

กันเล็กน้อย - ใช้ shadowRadius หรือ setShadowPath ไม่มีประเด็นในการทำทั้งสองอย่างเนื่องจากเป็นคำสั่งเดียวกันในบริบทนี้ (มุมมนทั้งหมด) จำเป็นต้องมี Shadowpath ที่คุณต้องการให้มีรูปร่างที่ซับซ้อนมากขึ้นหรือไม่ใช้มุมโค้งมนกับทุกมุม
Oliver Dungey

คำตอบ:


195

วิธีแก้ปัญหาเหล่านี้ไม่ได้ผลสำหรับฉัน หากคุณวางมุมมองย่อยทั้งหมดของคุณลงในมุมมองเนื้อหา 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

9
สิ่งนี้ใช้ได้ผลดีสำหรับฉันหลังจากที่ฉันเพิ่มcell.layer.backgroundColor = [UIColor clearColor].CGColor;
nacross

2
มีความคิดว่าทำไมสิ่งนี้ถึงปัดเฉพาะมุมบนของฉัน
user3344977

@ user3344977 อาจจะถูกตัดด้านล่าง? เช่นเดียวกับที่มุมจะโค้งมน แต่อยู่ใต้ส่วนที่มองเห็นได้ของเซลล์
CoderNinja

5
ฉันพบว่าสิ่งนี้ปัดเศษที่มุมบนของฉันและไม่ใช่มุมล่างของฉันด้วย
fatuhoku

2
คุณจะทำให้มุมอยู่รอบ ๆ ได้อย่างไรเมื่อคุณเลือก / ยกเลิกการเลือก / ย้ายเซลล์ มุมของฉันเป็นสี่เหลี่ยมจัตุรัสทุกครั้งที่ฉันหายใจในเซลล์หลังจากที่มันวาดอย่างถูกต้องในตอนแรก
Adrian

33

เวอร์ชัน 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

สนุก!


19

นี่คือโซลูชัน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

1
ทำงานได้อย่างรวดเร็ว 4,2 ด้วยเช่นกัน thanls
ShadeToD

3
ฉันกำลังมองหาวิธีแก้ปัญหา ... ขอบคุณน้อง Massimo: 'D
Massimo Polimeni

16

ตั้งค่าแอตทริบิวต์สำหรับมือถือที่ไม่ได้layercontentView

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

3
ดูเหมือนจะไม่ได้ผลสำหรับฉัน ฉันใช้รหัสที่คล้ายกันสำหรับ uitableviewcell แต่ดูเหมือนจะใช้ไม่ได้ใน collectionviewcell มันแปลกที่รหัสเดียวกันจะไม่ทำงานในเซลล์ cv
Jason

การอัปเดตความคิดเห็นข้างต้นของฉัน ฉันพบว่า UICollectionViewCells ดูเหมือนจะใช้การชดเชยเงาที่แตกต่างจาก UITableViewCells หากคุณไม่เห็นเงาให้ลองเปลี่ยนค่าชดเชย (การเพิ่มค่า Y ช่วยฉันได้)
Jason

15

SWIFT 4.2

ควรเพิ่มสิ่งนี้ในเซลล์หรือเซลล์ที่กำหนดเองของคุณ

        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

ซึ่งจะทำให้คุณได้เซลล์ที่มีขอบโค้งมนและเงาตกกระทบ


15

นี่คือคำตอบของฉันใกล้กับคนอื่น ๆ แต่ฉันเพิ่มรัศมีมุมให้กับเลเยอร์มิฉะนั้นมุมจะไม่ถูกต้อง นอกจากนี้จะทำให้ส่วนขยายของเล็ก ๆ น้อย ๆ 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

ดูเหมือนว่าเลเยอร์ใดก็ตามที่คุณกำลังปัดเศษจะถูกบดบังบางส่วนด้วยบางสิ่ง ไม่สามารถไปได้ไกลกว่านั้นหากไม่มีรายละเอียด
Timothy Moose

เฮ้ทิมฉันเพิ่งถามคำถามนี้ ฉันรู้สึกว่าคุณจะได้รับมันอย่างรวดเร็ว เป็นเพราะฉันมีแค่เงาที่ด้านล่าง / "ข้างใต้" เซลล์หรือเปล่า? stackoverflow.com/q/27929735/3344977
user3344977

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;

4

คำตอบของ Mike Sabatini ทำงานได้ดีหากคุณกำหนดค่าคุณสมบัติของเซลล์โดยตรงบน collectionView cellForItemAt แต่ถ้าคุณพยายามตั้งค่าในคลาสย่อย wakeFromNib () ของ UICollectionViewCell ที่กำหนดเองคุณจะลงท้ายด้วยการตั้งค่า bezierPath ที่ไม่ถูกต้องบนอุปกรณ์ที่ไม่ ไม่ตรงกับความกว้างและความสูงที่ตั้งไว้ก่อนหน้านี้ใน Storyboard (IB) ของคุณ

ทางออกสำหรับฉันคือสร้าง func ภายในคลาสย่อยของ UICollectionViewCell และเรียกมันจาก 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}
 }

4

ฉันใช้วิธีต่อไปนี้เพื่อให้ได้เอฟเฟกต์ประเภทนี้:

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

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

2

คุณสามารถตั้งค่าสีเงารัศมีและออฟเซ็ตในวิธีUICollectionViewDataSourceในขณะที่สร้าง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

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.