Додавання закругленого кута та тіні до UICollectionViewCell


105

Тож я вже пройшов різні публікації щодо додавання 2-го перегляду для додавання тіні, але все ще не можу змусити його працювати, якщо хочу додати його UICollectionViewCell. Я підкласифікую UICollectionViewCell, і ось мій код, де я додаю різні елементи інтерфейсу до перегляду вмісту комірки та додаю тінь до шару:

[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.


Я думаю, вам потрібно вдосконалити своє питання, щоб зрозуміти оточуючим. Це справді безладний те, що ти просив
— Дінеш Раджа

добре оновлено, я просто хочу знати, як додати закруглений кут і тінь до UICollectionViewCell
— Вінсент Йю

Трохи вбік - використовуйте shadowRadius АБО setShadowPath, немає жодного сенсу виконувати обидва, оскільки вони є по суті однаковою інструкцією в цьому контексті (усі закруглені кути). Тіньовий шлях необхідний там, де потрібні складніші форми або закруглені кути, які не застосовуються до всіх кутів.
— Олівер Данге

Відповіді:


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;
— nacross

2
Будь-яка ідея, чому це лише заокруглює мої верхні кути?
— user3344977

@ user3344977 можливо, дно відсікається? Як в кутах закруглені, але його під видимою частиною клітини
— CoderNinja

5
Я вважаю, що це заокруглює мої верхні кути, а не мої нижні кути.
— Фатухоку

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

Мені потрібно додати ефект тіні в правий кут і внизу кожної комірки, і, як працює наведений вище код, він заповнює клітинку тіньовим кольором ...
— Джо Сене,

25

У випадку, якщо це допомагає: ось швидкий спосіб закруглення кутів:

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

при цьому клітина є змінною, що керує коміркою: часто ви будете використовувати це в 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 ​​теж,
— дякую

2
Я шукав рішення ... спасибі молодшому Массімо: 'D
— Массімо

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. Дивно, як той самий код не працює в клітині відеоспостереження.
— Джейсон

Оновлення до мого вище коментаря. Я виявив, що 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
Будь-яка ідея, чому це лише круглі мої нижні кути?
— користувач3344977

Здається, будь-який шар, який ви округляєте, частково затьмарений чимось. Не можна піти далі без цього без деталей.
— Тимофі Мус

Гей, Тіме, я щойно задав це питання. У мене є відчуття, що ти зможеш це швидко отримати. Це тому, що у мене є тінь лише внизу / «під» клітиною? 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

Відповідь Майка Сабатіні прекрасно працює, якщо ви налаштуєте властивості комірок безпосередньо на collectionView cellForItemAt, але якщо ви спробуєте встановити їх у awakeFromNib () користувальницького підкласу UICollectionViewCell, ви закінчите неправильний набір bezierPath на пристроях, що не не відповідає ширині та висоті, встановленим раніше у вашій Раскадровці (IB).

Рішення для мене було створити функцію всередині підкласу UICollectionViewCell і викликати її з коміркиForItemAt так:

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

Ось мій погляд на рішення. Це схоже на інші відповіді, з однією ключовою різницею. Це не створює шлях, який залежить від меж зору. Будь-коли ви створюєте шлях на основі меж і надаєте його шару, який може зіткнутися з проблемами при його зміні розміру, і вам потрібно налаштувати методи для оновлення шляху.

Більш просте рішення - уникати використання нічого, що залежить від меж.

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, буде виконувати всю роботу всередині.


Найчистіша відповідь на мій погляд. Любіть ідею синхронізації радіусів.
— Кирило Кудаєв

2

Я виявив важливу річ: UICollectionViewCell повинен мати фоновий clearколір як колір, щоб зробити ці вище роботи.


Це ДУЖЕ важливо досягти, щоб не обрізати тінь! Не ігноруйте цю відповідь, дякую ЛОТЕ, чоловіче!
— DennyDog
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.