ios - 显示 UITableViewCell 时,CAGradientLayer 无法正确调整大小

标签 ios swift uitableview core-animation cagradientlayer

我正在开发一个应用程序,它在 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 时屏幕看起来像这样(我已删除敏感信息):

tableViewCell

请注意,右侧标签后面的颜色发生了变化。最后一个颜色列只是模拟器屏幕的边框。

你们知道如何解决这个问题吗?

编辑:更正标题上的拼写错误。

最佳答案

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/

相关文章:

ios - swift:将字符串转换为 double 问题

arrays - UserDefaults 数组连续返回 nil

swift - 在 Swift 的单行上测试 nil

ios - UIImage 没有出现

ios - iOS 5 中的 scrollviewTexturedBackgroundColor 是否发生了变化?

ios - 在 collectionViewCell 和 tableViewCell 中使用相同的 View

iphone - 如何布局项目 "relatively"而不是绝对位置?

ios - SpriteKit 和 Tiles - 处理非正方形的图 block

swift - Mac的屏幕共享状态

ios - 如何在 swift 中使用 Textfield 制作 UITableview?