问题
What you will see in the first image, if you scroll down a little bit, is the initial screen of a fin app. Basically, every section you see on the screen is placed within a vertical Stack View. Then every Label and Cell Is placed in a horizontal Stack View and so on, so the app auto-resizes for any screen size. I was using Story Board to create the elements.
The last section has two blue UITextFields that have a gradient layer behind it. I created an extension UITextField Class in a separate file that has the gradient function constructor in it and then another Class that placed the gradient behind any UITextField that have that class attached like this:
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
}
}
}
Now if you take a look at the second image on the right, the last section expands on tapping the Plus sign button. As a result, the third section(starting with Total) is hidden and a new stack view appears below within the same section. Everything resizes perfectly except the gradient layer. I have set a red background behind it which is the UITextField's Background, so the problem is highlighted. It appears that the Gradient Layer is shorter in height than the UITextField, which is its parent element.
Here's the full project on GitHub: https://github.com/silviuisidor/layerResizeProblem
How can I fix this?
回答1:
tl:dr — Instead of gradient layer that is a sublayer of the text field, you use a gradient view with the text field as its subview.
More details
Instead of a gradient layer, use a gradient view. The view exists purely to host a gradient layer as its underlying layer; you arrange this by subclassing UIView and implementing layerClass
to 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()
}
}
Now make the text field the subview of our gradient view. Pin it using autolayout to the center of the gradient view. The gradient view, with its text field subview, is what goes into the interface. When the animation takes place, it is the gradient view that is resized! And when that happens, the text field is automatically repositioned along with it.
回答2:
Resizing the layer frame in layoutSubviews
should solve your problem
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
}
}
来源:https://stackoverflow.com/questions/51543409/how-to-have-a-gradient-layers-size-placed-behind-a-uitextfield-match-the-uitex