Применить градиент к метке в UICollectionViewCell

Я пытаюсь применить градиент к UILabel в одной из ячеек в моем UICollectionView.

После некоторых ответов в Интернете я добавил расширение к UIImage:

extension UIImage {
    static func gradientImageWithBounds(bounds: CGRect, colors: [CGColor]) -> UIImage {
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = bounds
        gradientLayer.colors = colors
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)

        UIGraphicsBeginImageContext(gradientLayer.bounds.size)
        if let context = UIGraphicsGetCurrentContext() {
            gradientLayer.render(in: context )
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image!

        }
        return UIImage()
    }
}

и когда я применяю его к обычному ярлыку, он работает как шарм:

let gradientImage = UIImage.gradientImageWithBounds(bounds: someLabel.bounds, colors: [UIColor.black.cgColor, UIColor.white.cgColor])
someLabel.textColor = UIColor.init(patternImage: gradientImage)

Проблема в том, что метка, к которой я хочу применить градиент, является частью UICollectionViewCell, и когда я пытаюсь это сделать:

override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(nameLabel)
        nameLabel.snp.makeConstraints { (make) in
            make.top.bottom.trailing.equalToSuperview()
            make.leading.equalToSuperview().inset(10)
        }

        let gradientImage = UIImage.gradientImageWithBounds(bounds: nameLabel.bounds, colors: [UIColor.black.cgColor, UIColor.white.cgColor])
        nameLabel.textColor = UIColor.init(patternImage: gradientImage)
    }

это не работает. Когда я остановил выполнение прямо перед созданием градиентного изображения, к сожалению, nameLabel.bounds равно 0:

(lldb) po nameLabel.bounds
▿ (0.0, 0.0, 0.0, 0.0)
  ▿ origin : (0.0, 0.0)
    - x : 0.0
    - y : 0.0
  ▿ size : (0.0, 0.0)
    - width : 0.0
    - height : 0.0

Есть ли способ получить границы для метки в определении UICollectionViewCell? Зависит ли это от того, как я определяю UICollectionView? Что мне не хватает?

В качестве альтернативы, знаете ли вы какой-либо другой способ иметь метку внутри UICollectionViewCell с градиентом?

Я попытался установить размер в:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 100, height: 60)
}

Я попытался изменить определение макета с автоматического на

layout.estimatedItemSize = CGSize(width: 100, height: 60)

Кажется, ничего не помогает.


person Marta Panuszewska    schedule 16.06.2020    source источник
comment
Вероятно, это связано с тем, что во время инициализации кадр еще не определен. Что вы можете сделать, так это применить его, когда вы устанавливаете текст для метки внутри функции cellForItem.   -  person rs7    schedule 17.06.2020
comment
@rs7 На самом деле я начал оттуда, но в функции cellForItemAt nameLabel.bounds все еще был равен 0. Однако я попробовал еще раз и увидел, что cell.bounds не равен 0, и я могу работать с этим, так что спасибо! Интересно, почему рамка для самой метки еще не определена...   -  person Marta Panuszewska    schedule 17.06.2020
comment
Пожалуйста. Посмотрев еще раз на ваш код, я заметил, что вы размещаете свои представления внутри замыкания. Вы пытались переместить соответствующие 2 строки кода внутри замыкания? Это может решить проблему.   -  person rs7    schedule 17.06.2020


Ответы (1)


Я думаю, проблема может заключаться в том, что вы асинхронно размещаете свои представления внутри замыкания. Другими словами, прежде чем ваши представления будут размещены, выполняется следующий оператор, который объясняет, почему границы еще не установлены.

override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(nameLabel)
        nameLabel.snp.makeConstraints { (make) in
            make.top.bottom.trailing.equalToSuperview()
            make.leading.equalToSuperview().inset(10)
            let gradientImage = UIImage.gradientImageWithBounds(bounds: nameLabel.bounds, colors: [UIColor.black.cgColor, UIColor.white.cgColor])
            self.nameLabel.textColor = UIColor.init(patternImage: gradientImage)

        }
    }
person rs7    schedule 16.06.2020