我正在开发一个应用程序,它在 tableViewCell 内显示头像图片和一些个人资料信息。将相同的头像图片设置为单元格背景,然后我在其上方有另一个带有渐变的 UIView,该渐变是使用 CAGradientLayer 创建的。
问题是,当我的单元格显示时,渐变没有正确的帧大小(应该是单元格的大小),而是在右侧留下了一个空白空间。当我滚动 tableView 时,渐变大小正确调整。
这是我创建渐变的方法:
func awakeFromNib() {
let startColor = UIColor.gradientOverlay.cgColor //Defined elsewhere
let endColor = UIColor.black.cgColor
gradientLayer.frame = gradientView.frame
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
gradientLayer.colors = [startColor, endColor]
self.gradientView.layer.addSublayer(gradientLayer)
}
另外,我已经重写了 layoutSubviews
方法,如下所示:
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer.frame = gradientView.frame
self.layoutIfNeeded()
}
渲染 View 时屏幕看起来像这样(我已删除敏感信息):
请注意,右侧标签后面的颜色发生了变化。最后一个颜色列只是模拟器屏幕的边框。
你们知道如何解决这个问题吗?
编辑:更正标题上的拼写错误。
最佳答案
Gradient 本身使用的是 CAGradientLayer
,它是 CALayer
而不是 UIView
。所以 View 布局不会影响它。
自定义类
你可以使用我写的这个类:
class GradientView: UIView {
var colors: [UIColor]? { didSet { syncColors() } }
var direction: GradientDirection = .topToBottom {
didSet {
layer.startPoint = direction.startPoint
layer.endPoint = direction.endPoint
}
}
enum GradientDirection {
case rightToLeft
case leftToRight
case bottomToTop
case topToBottom
case custom(startPoint: CGPoint,endPoint: CGPoint)
var startPoint: CGPoint {
switch self {
case .rightToLeft: return CGPoint(x: 1, y: 0)
case .leftToRight: return .zero
case .bottomToTop: return CGPoint(x: 0, y: 1)
case .topToBottom: return .zero
case .custom(let startPoint, _): return startPoint
}
}
var endPoint: CGPoint {
switch self {
case .rightToLeft: return .zero
case .leftToRight: return CGPoint(x: 1, y: 0)
case .bottomToTop: return .zero
case .topToBottom: return CGPoint(x: 0, y: 1)
case .custom(_, let endPoint): return endPoint
}
}
static var interfaceDirection: GradientDirection {
switch UIApplication.shared.userInterfaceLayoutDirection {
case .leftToRight: return .leftToRight
case .rightToLeft: return .rightToLeft
}
}
}
override class var layerClass: AnyClass { return CAGradientLayer.self }
override var layer: CAGradientLayer { return super.layer as! CAGradientLayer }
override func layoutSubviews() { syncColors() }
private func syncColors() { layer.colors = colors?.map() { $0.cgColor } }
}
简化器类
借助这个简单的类:
enum GradientDirection {
case rightToLeft
case leftToRight
case bottomToTop
case topToBottom
case custom(startPoint: CGPoint,endPoint: CGPoint)
var startPoint: CGPoint {
switch self {
case .rightToLeft: return CGPoint(x: 1, y: 0)
case .leftToRight: return .zero
case .bottomToTop: return CGPoint(x: 0, y: 1)
case .topToBottom: return .zero
case .custom(let startPoint, _): return startPoint
}
}
var endPoint: CGPoint {
switch self {
case .rightToLeft: return .zero
case .leftToRight: return CGPoint(x: 1, y: 0)
case .bottomToTop: return .zero
case .topToBottom: return CGPoint(x: 0, y: 1)
case .custom(_, let endPoint): return endPoint
}
}
static var interfaceDirection: GradientDirection {
switch UIApplication.shared.userInterfaceLayoutDirection {
case .leftToRight: return .leftToRight
case .rightToLeft: return .rightToLeft
}
}
}
这样您就拥有了一个普通 View ,可以对来自 super View 的任何布局通知使用react。
用法
只需添加 subview 并将类设置为 GradientView
并使用自动布局或您想要的任何其他布局进行布局。
或使用代码:
let gradientView: GradientView = {
let gradientView = GradientView(frame: self.frame)
gradientView.colors = [
UIColor.black.withAlphaComponent(1),
UIColor.black.withAlphaComponent(0)
]
gradientView.direction = .bottomToTop
return gradientView
}()
请注意,如果您希望 View 具有一定的透明度,则需要删除 View 的原始 backgroundColor
。
关于ios - 显示 UITableViewCell 时,CAGradientLayer 无法正确调整大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58922327/