ios - CollectionViewCell 的子视图的渐变层仅在 View COntroller 首次进入时存在
问题描述
我有一个CollectionViewViewController
从另一个推过来的。这个CollectionViewViewController
视图有两个子视图:带有标签的简单 UIView 和UICollectionView
. 当它第一次出现时,一切正常,并且渐变显示正确。但是当我弹出这个视图控制器(所以它正在被释放)并从同一个父视图控制器再次推送它时,没有显示渐变。
单元格出列如下:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PageScrollGeminiCellIdentifier, for: indexPath) as! PageScrollGeminiCell
let item = viewModel.items[indexPath.item]
cell.configure(withTitle: item.name, description: item. description, imageURL: item.imageUrl, gradientColor: item.color, theme: theme)
mainView.geminiView.animateCell(cell)
return cell
}
这是我在单元格的类方法和单元格生命周期中所做的:
private var gradientColor: UIColor?
private var gradientLayer: CAGradientLayer?
[...]
override init(frame: CGRect) {
super.init(frame: .zero)
setupView()
}
required init?(coder aDecoder: NSCoder) {
return nil
}
override func layoutSubviews() {
if gradientLayer != nil {
gradientView.layer.sublayers = nil
}
if let color = gradientColor {
let gradientPoints = (CGPoint(x: 0.0, y: 0.15), CGPoint(x: 0.0, y: 1.0))
self.gradientLayer = gradientView.applyGradient(with: [color, color.withAlphaComponent(0.08)], gradient: .vertical(gradientPoints))
}
}
// MARK: Private
private func setupView() {
clipsToBounds = true
layer.cornerRadius = 15
backgroundColor = .clear
addSubview(containerView)
containerView.addSubview(backgroundImageView)
containerView.addSubview(gradientView)
containerView.addSubview(labelsContainerView)
labelsContainerView.addSubview(titleLabel)
labelsContainerView.addSubview(descriptionLabel)
containerView.snp.makeConstraints { maker in
maker.edges.equalToSuperview()
}
backgroundImageView.snp.makeConstraints { maker in
maker.edges.equalToSuperview()
}
gradientView.snp.makeConstraints { maker in
maker.leading.trailing.top.bottom.equalToSuperview()
}
labelsContainerView.snp.makeConstraints { maker in
maker.leading.top.equalTo(16)
maker.trailing.equalTo(-16)
}
titleLabel.snp.makeConstraints { maker in
maker.top.leading.trailing.equalToSuperview()
}
descriptionLabel.snp.makeConstraints { maker in
maker.top.equalTo(titleLabel.snp.bottom).offset(8)
maker.leading.trailing.bottom.equalToSuperview()
}
}
// MARK: - Internal
func configure(withTitle title: String?, description: String?, imageURL: String?, gradientColor: UIColor?, theme: Themeable) {
backgroundImageView.setImage(withString: imageURL)
titleLabel.text = title
titleLabel.font = theme.font.h2
descriptionLabel.text = description
descriptionLabel.font = theme.font.b1
self.gradientColor = gradientColor
}
我还想向您展示applyGradient
func:
func applyGradient(with colours: [UIColor], gradient orientation: GradientOrientation) -> CAGradientLayer {
layoutSubviews()
let gradient = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = colours.map { $0.cgColor }
gradient.startPoint = orientation.startPoint
gradient.endPoint = orientation.endPoint
gradient.cornerRadius = layer.cornerRadius
self.layer.insertSublayer(gradient, at: 0)
return gradient
}
我发现,当第一次显示 View Controller 时,layoutSubviews() 方法被调用了两次,但每次下一次每个单元格只调用一次。
现在我不确定我是否没有在我的单元格中插入超过 1 个子层,但我确定我正在清除子层数组,所以我认为这不是问题。
解决方案
layoutSubviews() 不应该被调用,应用程序会在需要时自行调用这个函数(这就是为什么它在开始时被调用两次)如 Swift 开发者网站所述: https ://developer.apple.com/documentation/uikit/ uiview/1622482-layoutsubviews
您不应直接调用此方法。如果要强制更新布局,请在下一次绘图更新之前调用 setNeedsLayout() 方法。如果要立即更新视图的布局,请调用 layoutIfNeeded() 方法。
尝试避免使用或调用 layoutSubviews(),相反,您可以尝试在 func 中设置 gradientLayer 变量,并在需要调用时调用它,尝试在 setupView() 下方
让我知道它是否有帮助。
推荐阅读
- templates - 为什么我收到模板类堆栈的分段错误?
- javascript - Javascript:带有数组和超时的承诺函数
- octave - 在程序以八度自动结束后重新运行程序
- javascript - 如何在 React Native 中使用 useState 在 AsyncStorage 中保存数据?
- asp.net-mvc - 在 C# 中以通用存储库模式调用数据库视图
- reactjs - 从 store 访问 state 和 props
- c# - C# 单选按钮 SQL Server
- routes - 在我在 Firefox 的 Angular 应用程序中的 accessiBe 中启用 Seizure Safe 配置文件后的导航问题
- html - 嵌入网站时如何仅循环播放我的 youtube 频道中的视频
- tensorflow - 为什么 Keras Embedding 层的 input_dim = vocab_size + 1