Додавання закругленого кута та тіні до 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.