April 24, 2020

How to design custom switch in iOS swift?

By Mohit Agrawal

Design custom UISwitch like the android from scratch in iOS swift.

custom ui switch image

We are going to copy the design of the android toggle button and design custom switch. It seems a lot of effort but believes me, my friends, I have made it very easy for you.

Let’s start some coding now. I will start with a basic class definition of the custom switch and named it “WarmodroidSwitch

class WarmodroidSwitch: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }
   
    required init?(coder: NSCoder) {
        //fatalError("init(coder:) has not been implemented")
        super.init(coder: coder)
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
    }
}

WarmodroidSwitch” is going to be our main class of type UIView. I will be designing this switch using just three-component and they are:

  1. A rectangle shape container view. (UIView)
  2. Elliptical shape more like a two-sided round rectangle. (UIView)
  3. And the thumb view. (UIView)

So let’s declare the views and properties as shown in code below:

class WarmodroidSwitch: UIView {
    
    private var containerView: UIView!
    private var elipticalView: UIView!
    private var thumb: UIView!

    var onThumbColor = UIColor.green
    var offThumbColor = UIColor.darkGray
    var onBackgroundColor = UIColor.gray
    var offBackgroungColor = UIColor.gray
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.commonInit()
    }
    
    required init?(coder: NSCoder) {
        //fatalError("init(coder:) has not been implemented")
        super.init(coder: coder)
        self.commonInit()
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        self.commonInit()
    }
    
    /**
            It will be called to initialize all the view and 
            properties.
     */
    private func commonInit() {
        
    }
}

The above code are self-explanatory, also I have defined one commonInit() function to initialize and set up all the views. Now I will be setting up views in commonInit() like this:

private func commonInit() {
        let padding = frame.size.height*0.15
        
        containerView = UIView()
        containerView.backgroundColor = UIColor.white
        containerView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(containerView)
        containerView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0).isActive = true
        containerView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0).isActive = true
        containerView.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true
        containerView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0).isActive = true
        
        elipticalView = UIView()
        //elipticalView.backgroundColor = UIColor.gray
        elipticalView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(elipticalView)
        elipticalView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding).isActive = true
        elipticalView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding).isActive = true
        elipticalView.topAnchor.constraint(equalTo: topAnchor, constant: padding).isActive = true
        elipticalView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -padding).isActive = true
        elipticalView.layer.cornerRadius = (frame.size.height - padding*2)/2
        
        thumb = UIView()
        //thumb.backgroundColor = UIColor.green
        thumb.translatesAutoresizingMaskIntoConstraints = false
        addSubview(thumb)
        thumbTrailingConstraint = thumb.trailingAnchor.constraint(equalTo: trailingAnchor)
        thumbTrailingConstraint.isActive = true
        setState()
        thumb.heightAnchor.constraint(equalToConstant: frame.size.height).isActive = true
        thumb.widthAnchor.constraint(equalToConstant: frame.size.height).isActive = true
        thumb.layer.cornerRadius = frame.size.height/2
        let thumbTapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapOnThumb))
        thumb.addGestureRecognizer(thumbTapGesture)
    }
@objc private func didTapOnThumb() {
        isOn = isOn ? false : true
        setState()
        delegate?.didTapSwitch(isON: isOn)
    }
    
    /**
     It gives nice animation to thumb when switched ON or OFF.
     Changes the color.
     */
    private func setState() {
        if isOn {
            UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseInOut, animations: {
                self.thumbTrailingConstraint.constant = 0
                self.layoutIfNeeded()
            }, completion: nil)
            elipticalView.backgroundColor = onBackgroundColor
            thumb.backgroundColor = onThumbColor
        } else {
            UIView.animate(withDuration: 0.2,delay: 0.0, options: .curveEaseInOut, animations: {
                self.thumbTrailingConstraint.constant = -self.frame.size.width/2
                self.layoutIfNeeded()
            }, completion: nil)
            elipticalView.backgroundColor = offBackgroungColor
            thumb.backgroundColor = offThumbColor
        }
    }

You will find two more functions below commonInit() are: didTapOnThumb() and setState().

  • didTapOnThumb(): This function will notify the delegate that user has clicked the button and the state has been changed.
  • setState(): This function will be used to set the ON and OFF state of the button.

Find the complete source code link for how to design custom switch in iOS swift from scratch is here

Help me to grow our YouTube Channel: More tutorials like this

I hope this blog post is useful for you, do let me know your opinion in the comment section below.
I will be happy to see your comments down below 👏.
Thanks for reading!!!

Can I make a custom switch in iOS swift?

custom switch

Yes, either you can customise the existing UISwitch or you can even design your own from the scratch. Check this blog post for complete tutorial.