Reputation: 6158
Here is my custom button:
class GradientButton: UIButton {
private var colors: [UIColor] = [.white]
private var direction: GradientDirection = .leftToRight
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(colors: [UIColor], direction: GradientDirection) {
self.init()
self.colors = colors
self.direction = direction
}
override func layoutSubviews() {
self.backgroundColor = UIColor.gradientColorWith(bounds: self.bounds, colors: self.colors, direction: self.direction)
}
}
And gradient color:
enum GradientDirection {
case topToBottom
case leftToRight
case bottomToTop
case rightToLeft
case leftTopToRightBottom
case leftBottomToRightTop
case rightTopToLeftBottom
case RightBottomToLeftTop
}
extension UIColor {
static func gradientColorWith(bounds: CGRect, colors: [UIColor], direction: GradientDirection) -> UIColor {
var cgColorArray: [CGColor] = []
for color in colors {
cgColorArray.append(color.cgColor)
}
UIGraphicsBeginImageContextWithOptions(bounds.size, true, 1)
guard let context = UIGraphicsGetCurrentContext() else { return .white }
context.saveGState();
let colorSpace = colors.last?.cgColor.colorSpace
let gradient = CGGradient.init(colorsSpace: colorSpace, colors: cgColorArray as CFArray, locations: nil)!
var startPoint = CGPoint.zero
var endPoint = CGPoint.zero
let width = bounds.size.width
let height = bounds.size.height
switch direction {
case .topToBottom:
startPoint = CGPoint.init(x: 0, y: 0)
endPoint = CGPoint.init(x: 0, y: height)
case .leftToRight:
startPoint = CGPoint.init(x: 0, y: 0)
endPoint = CGPoint.init(x: width, y: 0)
case .bottomToTop:
startPoint = CGPoint.init(x: 0, y: height)
endPoint = CGPoint.init(x: 0, y: 0)
case .rightToLeft:
startPoint = CGPoint.init(x: width, y: 0)
endPoint = CGPoint.init(x: 0, y: 0)
case .leftTopToRightBottom:
startPoint = CGPoint.init(x: 0, y: 0)
endPoint = CGPoint.init(x: width, y: height)
case .leftBottomToRightTop:
startPoint = CGPoint.init(x: 0, y: height)
endPoint = CGPoint.init(x: width, y: 0)
case .rightTopToLeftBottom:
startPoint = CGPoint.init(x: width, y: 0)
endPoint = CGPoint.init(x: 0, y: height)
case .RightBottomToLeftTop:
startPoint = CGPoint.init(x: width, y: height)
endPoint = CGPoint.init(x: 0, y: 0)
}
context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: .drawsBeforeStartLocation)
let image = UIGraphicsGetImageFromCurrentImageContext()!
context.restoreGState()
UIGraphicsEndImageContext()
return UIColor.init(patternImage: image)
}
}
It's work perfect with UILabel,however,title disappeared on UIButton:
private lazy var gradientButton: GradientButton = {
let gradientButton = GradientButton.init(colors: [UIColor.orange, UIColor.purple], direction: .leftToRight)
gradientButton.setTitle("This is a Button", for: .normal)
gradientButton.setTitleColor(.black, for: .normal)
gradientButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 30)
return gradientButton
}()
So I wonder Why title disappeared?
How to solve it?
Note:I say color,so do not tell me add a layer or inset a layer.
Upvotes: 0
Views: 176
Reputation: 535232
It's because your implementation of layoutSubviews
is wrong. You never call super
so the button never actually gets laid out.
Let's fix it:
override func layoutSubviews() {
super.layoutSubviews()
self.backgroundColor = UIColor.gradientColorWith(bounds: self.bounds, colors: self.colors, direction: self.direction)
}
Let's test it:
let b = self.gradientButton
b.sizeToFit()
b.frame.origin = CGPoint(x: 50, y: 50)
self.view.addSubview(b)
Upvotes: 1