0

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

looks now

I want to see

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
}
} 
Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
Sergey
  • 37
  • 7
  • Please show, how's your button should looks ? – Sagar Chauhan Jul 02 '18 at 17:20
  • I tried to add images. But the whole code is here. If you launch it now, I will see how it looks. If you uncomment line 21 and 22, you will see how it should look like. But the button should keep the proportions when you click. – Sergey Jul 02 '18 at 17:34
  • For this, you can use normal button and set background colour for same. It's very easy and preferable instead of creating custom class. – Sagar Chauhan Jul 02 '18 at 17:45
  • Hi, zombie’s answer could be correct. Does your problem exist now? – Shamim Hossain Jul 02 '18 at 18:03
  • No, I can not. Normal button with background color will not decrease when pressed. – Sergey Jul 02 '18 at 18:09
  • Honestly, it's not a _"very good-looking button"_. It's just an OK looking button. – Ashley Mills Jul 02 '18 at 20:19
  • remove this line `button.layer.masksToBounds = true` – zombie Jul 02 '18 at 20:22
  • @zombie, I tried this already. It does not help. Also if I delete the previous line: "button.layer.cornerRadius = 10", there will be no rounded corners. So, I think the problem is somewhere in "override func awakeFromNib()" – Sergey Jul 02 '18 at 20:47

2 Answers2

1

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
    }
}
zombie
  • 5,069
  • 3
  • 25
  • 54
  • No, I tried UIControlState(), and it still don't work. With utton.backgroundColor = .orange the button will not even decrease when pressed. – Sergey Jul 02 '18 at 18:07
  • @Sergey check my updated answer for making the button shrink (should work with background color and layer.cornerRadius) – zombie Jul 02 '18 at 18:17
  • Yes, it works. Thank you. But there are a couple of nuances. The button reacts a bit slower - at first I thought it sounded, but really a bit slower. Of course this is not a problem in general. Also I do not see the title of the button, although it is set. – Sergey Jul 02 '18 at 18:37
  • @Sergey I made it a little bit faster by changing the duration also the animation is inside the override now – zombie Jul 02 '18 at 18:39
  • Really. I did not notice "UIView.animate(withDuration: 0.1)" :( It's much better now. But I still can not see the title. – Sergey Jul 02 '18 at 18:44
  • And is there any way to add a shadow to this button? – Sergey Jul 02 '18 at 18:53
  • @Sergey that should be another question but anyway I updated the answer again – zombie Jul 02 '18 at 18:56
  • Thank you very much @zombie. Your decision for the button itself with the is very elegant. But I can not see the shadow. Perhaps I'm doing something wrong by calling a button. – Sergey Jul 02 '18 at 19:22
  • upload a sample to github – zombie Jul 02 '18 at 19:26
  • can I just add the code to my first question? There is only one page there. – Sergey Jul 02 '18 at 19:48
0

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.

Sergey
  • 37
  • 7