web-dev-qa-db-fra.com

Ajout d'un coin arrondi et d'une ombre portée à UICollectionViewCell

Donc, je suis déjà passé par divers articles sur l’ajout d’une 2e vue pour ajouter une ombre, mais je ne peux toujours pas le faire fonctionner si je veux l’ajouter dans UICollectionViewCell. J'ai sous-classé UICollectionViewCell, et voici mon code dans lequel j'ajoute divers éléments d'interface utilisateur à la vue du contenu de la cellule et ajoute une ombre au calque:

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

Je voudrais savoir comment ajouter un coin arrondi et une ombre à UICollectionViewCell.

81
Vincent Yiu

Aucune de ces solutions n'a fonctionné pour moi. Si vous placez toutes vos sous-vues dans la vue de contenu UICollectionViewCell, ce que vous êtes probablement, vous pouvez définir l'ombre sur le calque de la cellule et la bordure sur le calque de contentView pour obtenir les deux résultats.

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
168
Mike Sabatini

Swift 3 version:

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
27
Torre Lasley

Si cela peut aider: Voici le Swift pour arrondir les angles:

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

avec cellule étant une variable contrôlant la cellule: vous utiliserez souvent ceci dans override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell

Prendre plaisir!

23
rocket101

Définissez les attributs layer pour la cellule et non pas 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]];
14
inzonemobileDev

Voici la solution Swift 4, mise à jour pour arrondir les angles tous et pas uniquement les coins supérieurs:

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
10
Massimo Polimeni

Vous devez simplement (a) définir cornerRadius et (b) définir shadowPath pour qu'il soit un rectangle arrondi ayant le même rayon que cornerRadius:

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

Swift 4.2

Il faut ajouter ceci dans votre cellule personnalisée ou cellForItemAt: Si vous utilisez la méthode cellForItemAt: substitute 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

Cela vous donnera une cellule avec une bordure arrondie et une ombre portée.

7
Alexander

J'ai dû faire de légers changements pour 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;
6
Keith Holliday

Celui-ci a fonctionné pour moi

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

La réponse de Mike Sabatini fonctionne bien, si vous configurez les propriétés de la cellule directement sur la collectionView cellForItemAt, mais si vous essayez de les définir dans awakeFromNib () d'une sous-classe UICollectionViewCell personnalisée, vous vous retrouverez avec un mauvais jeu bezierPath sur les périphériques qui ne le sont pas. ne correspond pas à la largeur et à la hauteur précédemment définies dans votre Storyboard (IB).

La solution pour moi était de créer une fonction dans la sous-classe d’UICollectionViewCell et de l’appeler à partir de cellForItemAt comme suit:

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

Et sur le 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}
 }
2
frantenerelli

Vous pouvez définir la couleur de l'ombre, le rayon et le décalage dans UICollectionViewDataSource lors de la création d'une méthode ICollectionViewCell

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
1
Rahul Panzade

Voici mon point de vue sur la solution. Cela ressemble aux autres réponses, avec une différence essentielle. Cela ne crée pas de chemin qui dépend des limites de la vue. Chaque fois que vous créez un chemin basé sur les limites et le fournissez à la couche, vous pouvez rencontrer des problèmes lors de son redimensionnement et vous devez configurer des méthodes pour mettre à jour le chemin.

Une solution plus simple consiste à éviter d’utiliser tout élément dépendant des limites.

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

Maintenant, chaque fois que la taille des cellules change, l’API de la vue effectue tout le travail en interne.

0
Adam

Voici ma réponse, proche des autres, mais j'ajoute un rayon de coin au calque, sinon les coins ne se rempliront pas correctement. En outre, cela fait une jolie petite extension sur 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
}

}

Vous pouvez l'appeler dans collectionView(_:cellForItemAt:) de la source de données une fois que vous avez retiré votre cellule de la file d'attente.

0
smileBot

Si vous chargez la cellule à partir d'un xib, alors awakeFromNib est l'endroit où placer le code.

class MyCollectionViewCell: UICollectionViewCell {
    override func awakeFromNib() {
        layer.cornerRadius = 7
        layer.masksToBounds = true
    }
}
0
RefuX