丸い角とドロップシャドウをUICollectionViewCellに追加する


104

したがって、シャドウを追加するための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 '22

更新しました。UICollectionViewCellに丸みを帯びた角と影を追加する方法を知りたいだけです
Vincent Yiu

少し脇に置きます-shadowRadiusまたはsetShadowPathを使用します。これらは、このコンテキストでは本質的に同じ命令(すべての角が丸い)であるため、両方を実行しても意味がありません。すべてのコーナーに適用されない、より複雑な形状または丸みを帯びたコーナーが必要な場合は、シャドウパスが必要です。
Oliver Dungey

回答:


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;

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;
ナクロス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

cellは、セルを制御する変数です。多くの場合、これは override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell

楽しい!


18

ここでは、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でも動作します。ありがとう
ShadeToD

2
私は解決策を探していました...若いマッシモに感謝します: '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セルで機能しないのは奇妙です。
Jason

上記のコメントの更新。UICollectionViewCellsはUITableViewCellsとは異なるシャドウオフセットを使用しているようです。影が表示されない場合は、オフセットを変更してみてください(Y値を増やすと効果的です)。
Jason

14

SWIFT 4.2

これをカスタムセルまたはcellForItemAtに追加する必要があります:cellForItemAtを使用している場合:自己置換->セル

        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

cornerRadius(a)を設定shadowPathし、(b)と同じ半径の丸みを帯びた長方形にする必要がありますcornerRadius

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

2
なぜこれが私の下隅だけを丸めるのですか?
user3344977

丸めているレイヤーが何かによって部分的に隠されているように聞こえます。詳細がなければそれ以上先に進むことはできません。
ティモシームース2015年

ティムさん、この質問をしました。早く手に入れられる気がします。セルの下/下にのみ影があるからですか?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;

3

Mike Sabatiniの答えは正常に機能します。collectionViewcellForItemAtでセルプロパティを直接構成した場合、カスタム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

あなたは、影の色を設定し、半径にオフセットすることができます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

これが私の解決策です。これは他の回答と似ていますが、重要な違いが1つあります。ビューの境界に依存するパスは作成されません。境界に基づいてパスを作成し、それをレイヤーに提供すると、サイズ変更時に問題が発生する可能性があり、パスを更新するメソッドをセットアップする必要があります。

より簡単な解決策は、境界に依存するものの使用を避けることです。

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は、clear上記のこれらを機能させるために、backgroundColorを色として持つ必要があります。


これは、影を落とさないようにするために非常に重要です!この回答を無視しないでください。ありがとうございます。
DennyDog
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.