重新调整布局大小后,如何将渐变层的大小放置在 UITextField 后面,匹配 UITextField 大小?

How to have a Gradient Layer's size placed behind a UITextField, match the UITextField size, after re-sizing the layout?

如果向下滚动一点,您将在第一张图片中看到的是 fin 应用程序的初始屏幕。基本上,您在屏幕上看到的每个部分都放置在垂直堆栈视图中。然后每个 Label 和 Cell 都被放置在一个水平的 Stack View 中等等,所以应用程序会自动调整大小以适应任何屏幕尺寸。我正在使用 Story Board 来创建元素。

最后一部分有两个蓝色的 UITextField,它们后面有一个渐变层。我在一个单独的文件中创建了一个扩展 UITextField Class,其中包含渐变函数构造函数,然后另一个 Class 将渐变放置在任何具有 class 附加的 UITextField 后面,如下所示:

extension UITextField {
    func gradientBackground(firstColor: UIColor, secondColor: UIColor){
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = bounds
        gradientLayer.colors = [firstColor.cgColor, secondColor.cgColor]
        gradientLayer.locations = [0.0, 1.0]
        gradientLayer.startPoint = CGPoint(x:0.0, y:0.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
        layer.addSublayer(gradientLayer)
    }
}

class gradientToTextField: UITextField {
    var once = true
    override func layoutSubviews() {
        super.layoutSubviews()
        if once {
            self.gradientBackground(firstColor: UIColor(red: 0.30, green: 0.55, blue: 1.00, alpha: 1), secondColor: UIColor(red: 0.00, green: 0.36, blue: 1.00, alpha: 1))
            once = false
        }
    }
}

现在,如果您看一下右边的第二张图片,最后一部分会在点击加号按钮时展开。结果,第三部分(从 Total 开始)被隐藏,新的堆栈视图出现在同一部分的下方。除渐变层外,所有内容都可以完美调整大小。我在它后面设置了一个红色背景,这是 UITextField 的背景,因此问题突出显示。 Gradient Layer 的高度似乎比它的父元素 UITextField 矮。

这是 GitHub 上的完整项目:https://github.com/silviuisidor/layerResizeProblem

我该如何解决这个问题?

tl:dr — 您可以使用以文本字段作为其子视图的渐变视图,而不是作为文本字段子层的渐变层。

更多详情

使用渐变层 view 而不是渐变层。视图的存在纯粹是为了承载一个渐变层作为其底层;你通过子类化 UIView 并实现 layerClass 到 return CAGradientLayer.self.

来安排这个
class MyGradientView : UIView {
    override class var layerClass : AnyClass { return CAGradientLayer.self }
    private func config() {
        let gradientLayer = self.layer as! CAGradientLayer
        let firstColor = UIColor(red: 0.30, green: 0.55, blue: 1.00, alpha: 1)
        let secondColor = UIColor(red: 0.00, green: 0.36, blue: 1.00, alpha: 1)
        gradientLayer.colors = [firstColor.cgColor, secondColor.cgColor]
        gradientLayer.locations = [0.0, 1.0]
        gradientLayer.startPoint = CGPoint(x:0.0, y:0.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
    }
    override init(frame: CGRect) {
        super.init(frame:frame)
        self.config()
    }
    required init?(coder: NSCoder) {
        super.init(coder:coder)
        self.config()
    }
}

现在让文本字段成为渐变视图的 子视图。使用自动布局将其固定到渐变视图的中心。渐变视图及其文本字段子视图是进入界面的内容。当动画发生时,调整大小的是渐变视图!当发生这种情况时,文本字段会自动随之重新定位。

layoutSubviews 中调整图层框的大小应该可以解决您的问题

extension UITextField {
    func gradientBackground(firstColor: UIColor, secondColor: UIColor) -> CAGradientLayer{
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = bounds
        gradientLayer.colors = [firstColor.cgColor, secondColor.cgColor]
        gradientLayer.locations = [0.0, 1.0]
        gradientLayer.startPoint = CGPoint(x:0.0, y:0.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
        layer.addSublayer(gradientLayer)
        return gradientLayer
    }
}

class gradientToTextField: UITextField {
    var coloredLayer : CAGradientLayer! = nil

    var once = true
    override func layoutSubviews() {
        super.layoutSubviews()
        if once {
            coloredLayer = self.gradientBackground(firstColor: UIColor(red: 0.30, green: 0.55, blue: 1.00, alpha: 1), secondColor: UIColor(red: 0.00, green: 0.36, blue: 1.00, alpha: 1))
            once = false
        }
        coloredLayer.frame = self.bounds
    }
}