我有一个带有 UITableView 的应用程序。我们正在逐渐转换为 SwiftUI,因此 UITableView 基本上是 SwiftUI 视图的集合。我能够使用这两个函数让背景显示为渐变:
func createBackgroundGradient() -> CAGradientLayer {
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor.red.cgColor, UIColor.white.cgColor, UIColor.red.cgColor]
gradientLayer.locations = [0.0, 0.5, 1.0]
gradientLayer.frame = self.tableView.bounds
return gradientLayer
}
func refreshBackground() {
tableView.backgroundView = nil
let backgroundView = UIView()
let gradientView = createBackgroundGradient()
backgroundView.layer.addSublayer(gradientView)
tableView.backgroundView = backgroundView
}
我从 viewWillLayoutSubview 调用这个函数,因为当我们从后端获取数据时,我会弹出视图。这用于设置屏幕长度的渐变。但是,我希望渐变占据整个 UITableView,并且希望它与表视图一起滚动(比屏幕的长度长得多),而不仅仅是坐在背景中,单元格在其上滚动.
这个问题的解决方案:UIScrollView的渐变背景色看起来像我想要的行为,但是当我将refreshBackround函数更改为这样时:
func refreshBackground() {
if let gradientSublayer = self.gradientSublayer {
gradientSublayer.removeFromSuperlayer()
}
self.gradientSublayer = createBackgroundGradient()
tableView.layer.insertSublayer(self.gradientSublayer ?? createBackgroundGradient(), at: 0)
}
我没有看到任何行为差异 - 它仍然只是屏幕的长度,并且当我滚动时它不会改变位置。
有人知道解决这个问题的方法吗?我考虑过尝试用渐变的不同部分对不同部分进行着色,但这似乎会变得非常复杂,因为根据我们获取的数据,表中的各个部分可能存在也可能不存在后端(它可能看起来很糟糕,因为填充这些部分时渐变的部分会弹出)。
为了让
gradientLayer
完全占据UITableView
。您需要订阅 tableView
的绑定更改,并且 refreshBackground
基于新的 bounds
。这是使用 Combine
的方法:
tableView.publisher(for: \.bounds)
.removeDuplicates()
.sink { [weak self] size in
self?.createBackgroundGradient()
}
.store(in: &cancels)
var gradientLayer: CAGradientLayer!
func createBackgroundGradient() {
if let gradientSublayer = self.gradientLayer {
gradientSublayer.removeFromSuperlayer()
}
gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor.red.cgColor, UIColor.white.cgColor, UIColor.red.cgColor]
gradientLayer.locations = [0.0, 0.5, 1.0]
gradientLayer.zPosition = -1000
gradientLayer.frame = self.collectionView.bounds
tableView.layer.insertSublayer(self.gradientLayer, at: 0)
}