显示 UITableViewCell 时,CAGradientLayer 无法正确调整大小
CAGradientLayer not resizing correctly when UITableViewCell is shown
我正在开发一个在 tableViewCell 中显示头像图片和一些个人资料信息的应用程序。同样的头像图片设置为单元格背景,然后我在它上面有另一个带有渐变的UIView,它是使用CAGradientLayer创建的。
问题是,当我的单元格显示时,渐变没有正确的框架大小(应该是单元格的大小),而是在右边留下一个空 space。当我滚动 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()
}
呈现视图时的屏幕如下所示(我已删除敏感信息):
请注意,在右侧的标签之后,颜色发生了变化。最后一列颜色只是模拟器屏幕的边框。
你们知道如何解决这个问题吗?
编辑:更正了标题上的拼写错误。
渐变原生使用 CAGradientLayer
是 CALayer
而不是 UIView
。所以视图布局不会影响它。
自定义class
你可以用这个class我写的:
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() { [=10=].cgColor } }
}
简化器class
在这个简单的帮助下 class:
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
}
}
}
这样你就有了一个普通视图,它对来自超级视图的任何布局通知做出反应。
用法
只需添加子视图并将 class 设置为 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
}()
请注意,如果您希望视图具有一定的透明度,您需要删除视图的原始 backgroundColor
。
我找到了解决方法。由于问题出在层的宽度上,我使用 UIScreen.main.bounds.width
.
初始化了它的宽度
我正在开发一个在 tableViewCell 中显示头像图片和一些个人资料信息的应用程序。同样的头像图片设置为单元格背景,然后我在它上面有另一个带有渐变的UIView,它是使用CAGradientLayer创建的。
问题是,当我的单元格显示时,渐变没有正确的框架大小(应该是单元格的大小),而是在右边留下一个空 space。当我滚动 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()
}
呈现视图时的屏幕如下所示(我已删除敏感信息):
请注意,在右侧的标签之后,颜色发生了变化。最后一列颜色只是模拟器屏幕的边框。
你们知道如何解决这个问题吗?
编辑:更正了标题上的拼写错误。
渐变原生使用 CAGradientLayer
是 CALayer
而不是 UIView
。所以视图布局不会影响它。
自定义class
你可以用这个class我写的:
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() { [=10=].cgColor } }
}
简化器class
在这个简单的帮助下 class:
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
}
}
}
这样你就有了一个普通视图,它对来自超级视图的任何布局通知做出反应。
用法
只需添加子视图并将 class 设置为 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
}()
请注意,如果您希望视图具有一定的透明度,您需要删除视图的原始 backgroundColor
。
我找到了解决方法。由于问题出在层的宽度上,我使用 UIScreen.main.bounds.width
.