Reputation: 37
I have a very good-looking button.
import UIKit
class NiseButtonVC: UIViewController {
var button = MyShrinkingButton()
var button2 = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
button = MyShrinkingButton()
button.bounds = CGRect(x: 0, y: 0, width: 200, height: 80)
button.center = view.center
button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
button.setTitle("button", for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 40)
button.titleLabel?.adjustsFontSizeToFitWidth = true
let backGroundImage = UIImage.from(color: .orange)
button.setBackgroundImage(backGroundImage, for: .normal)
button.adjustsImageWhenHighlighted = false
// button.layer.cornerRadius = 10
// button.layer.masksToBounds = true
view.addSubview(button)
}
@objc func buttonPressed(sender: UIButton){
print("button pressed")
}
}
extension CGSize {
func sizeByDelta(dw:CGFloat, dh:CGFloat) -> CGSize {
return CGSize(width:self.width + dw, height:self.height + dh)
}
}
class MyShrinkingButton: UIButton {
override func backgroundRect(forBounds bounds: CGRect) -> CGRect {
var result = super.backgroundRect(forBounds:bounds)
if self.isHighlighted {
result = result.insetBy(dx: 3, dy: 3)
}
return result
}
override var intrinsicContentSize : CGSize {
return super.intrinsicContentSize.sizeByDelta(dw:25, dh: 20)
}
override func titleRect(forContentRect bounds: CGRect) -> CGRect {
var result = super.titleRect(forContentRect:bounds)
if self.isHighlighted {
result = result.insetBy(dx: 3, dy: 3)
}
return result
}
}
extension UIImage {
static func from(color: UIColor) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor)
context!.fill(rect)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}
}
But I want the button to have rounded edges. I can do it using cornerRadius for .normal state, but when button is pressed the effect disappears. In truth I would like to add shadow to the button, and I can add shadow itself, but I have no idea how to combine shadow and rounded edges.
looks now
I want to see
I can not use button.backgroundColor instead of button.setBackgroundColor, because then the button will not decrease when you click. This I found out a couple of weeks ago: What is the method "backgroundRect(forBounds:)" of UIButton used for?
Final code. Only shadow don't work. But the corner radius also work only fro viewDidLoad:
import UIKit
class ViewController: UIViewController {
var button = ShrinkingButton()
override func viewDidLoad() {
super.viewDidLoad()
button = ShrinkingButton()
button.bounds = CGRect(x: 0, y: 0, width: 200, height: 80)
button.center = view.center
button.setTitle("button", for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 40)
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.backgroundColor = .orange
button.setTitleColor(.white, for: .normal)
button.adjustsImageWhenHighlighted = false
button.layer.cornerRadius = 10
button.layer.masksToBounds = true
view.addSubview(button)
}
}
class ShrinkingButton: UIButton {
override var isHighlighted: Bool {
didSet {
UIView.animate(withDuration: 0.1) {
self.isHighlighted ? self.layer.setAffineTransform(CGAffineTransform(scaleX: 0.9, y: 0.9 )) :
self.layer.setAffineTransform(.identity)
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
layer.cornerRadius = 10
layer.shadowOffset = CGSize(width: -1, height: 2)
layer.shadowRadius = 5
layer.shadowOpacity = 0.5
}
}
Upvotes: 0
Views: 189
Reputation: 37
Finally, this code works
import UIKit
class NiseButtonwhithShadowVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// constants
let radius: CGFloat = 20, dimension: CGFloat = 200, offset = 4
let frame = CGRect(x: 0, y: 0, width: 200, height: 50)
// custom view
let customView = ShrinkingButton2(frame: frame)
customView.setTitle("Button", for: .normal)
// image layer
let imageLayer = CALayer()
imageLayer.backgroundColor = UIColor.orange.cgColor
imageLayer.masksToBounds = true
imageLayer.frame = frame
imageLayer.cornerRadius = radius
imageLayer.masksToBounds = true
// rounded layer
let roundedLayer = CALayer()
roundedLayer.shadowColor = UIColor.gray.cgColor
roundedLayer.shadowPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: dimension, height: 50), cornerRadius: radius).cgPath
roundedLayer.shadowOffset = CGSize(width: offset, height: offset)
roundedLayer.shadowOpacity = 0.5
roundedLayer.shadowRadius = 2
roundedLayer.frame = frame
// views and layers hierarchy
customView.layer.addSublayer(imageLayer)
customView.layer.insertSublayer(roundedLayer, below: imageLayer)
view.addSubview(customView)
// layout
customView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
}
}
class ShrinkingButton2: UIButton {
override var isHighlighted: Bool {
didSet {
UIView.animate(withDuration: 0.1) {
self.isHighlighted ? self.layer.setAffineTransform(CGAffineTransform(scaleX: 0.95, y: 0.95 )) :
self.layer.setAffineTransform(.identity)
}
}
}
}
Thanks to everyone who helped me.
Upvotes: 0
Reputation: 5259
The button disappears because you set the background image to the normal state only.
That means for any other state the button does not have a background image.
A better approach would be to set the background color instead of the image
button.backgroundColor = .orange
If you want to use a background image which is not just a color then maybe you can use this
button.setBackgroundImage(image, for: UIControlState())
To create a shrinking effect on press with showdow
import UIKit
class ShrinkingButton: UIButton {
override var isHighlighted: Bool {
didSet {
UIView.animate(withDuration: 0.1) {
self.isHighlighted ? self.layer.setAffineTransform(CGAffineTransform(scaleX: 0.9, y: 0.9 )) :
self.layer.setAffineTransform(.identity)
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
layer.cornerRadius = 10
layer.shadowOffset = CGSize(width: -1, height: 2)
layer.shadowRadius = 5
layer.shadowOpacity = 0.5
}
}
Upvotes: 1