Instantly share code, notes, and snippets.

Embed
What would you like to do?
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
class Responder: NSObject {
@objc func segmentedControlValueChanged(_ sender: UISegmentedControl) {
UIView.animate(withDuration: 0.3) {
buttonBar.frame.origin.x = (segmentedControl.frame.width / CGFloat(segmentedControl.numberOfSegments)) * CGFloat(segmentedControl.selectedSegmentIndex)
}
}
}
let responder = Responder()
// Container view
let view = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 100))
view.backgroundColor = .white
let segmentedControl = UISegmentedControl()
// Add segments
segmentedControl.insertSegment(withTitle: "One", at: 0, animated: true)
segmentedControl.insertSegment(withTitle: "Two", at: 1, animated: true)
segmentedControl.insertSegment(withTitle: "Three", at: 2, animated: true)
// First segment is selected by default
segmentedControl.selectedSegmentIndex = 0
segmentedControl.backgroundColor = .clear
segmentedControl.tintColor = .clear
segmentedControl.setTitleTextAttributes([
NSAttributedStringKey.font : UIFont(name: "DINCondensed-Bold", size: 18),
NSAttributedStringKey.foregroundColor: UIColor.lightGray
], for: .normal)
segmentedControl.setTitleTextAttributes([
NSAttributedStringKey.font : UIFont(name: "DINCondensed-Bold", size: 18),
NSAttributedStringKey.foregroundColor: UIColor.orange
], for: .selected)
// This needs to be false since we are using auto layout constraints
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
let buttonBar = UIView()
// This needs to be false since we are using auto layout constraints
buttonBar.translatesAutoresizingMaskIntoConstraints = false
buttonBar.backgroundColor = UIColor.orange
// Add the segmented control to the container view
view.addSubview(segmentedControl)
view.addSubview(buttonBar)
// Constrain the segmented control to the top of the container view
segmentedControl.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
// Constrain the segmented control width to be equal to the container view width
segmentedControl.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
// Constrain the height of the segmented control to an arbitrarily chosen value
segmentedControl.heightAnchor.constraint(equalToConstant: 40).isActive = true
// Constrain the top of the button bar to the bottom of the segmented control
buttonBar.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor).isActive = true
buttonBar.heightAnchor.constraint(equalToConstant: 5).isActive = true
// Constrain the button bar to the left side of the segmented control
buttonBar.leftAnchor.constraint(equalTo: segmentedControl.leftAnchor).isActive = true
// Constrain the button bar to the width of the segmented control divided by the number of segments
buttonBar.widthAnchor.constraint(equalTo: segmentedControl.widthAnchor, multiplier: 1 / CGFloat(segmentedControl.numberOfSegments)).isActive = true
segmentedControl.addTarget(responder, action: #selector(responder.segmentedControlValueChanged(_:)), for: UIControlEvents.valueChanged)
PlaygroundPage.current.liveView = view
@hazelf42

This comment has been minimized.

Copy link

hazelf42 commented Nov 23, 2018

Hello! If we're doing this within an app, do we want all the code to be in ViewDidLoad? I keep getting errors because of the @objc code, which, if taken out of ViewDidLoad, stops working

(I'm new at this, can you tell?)

@tonespy

This comment has been minimized.

Copy link

tonespy commented Jan 15, 2019

FuturePriceDaysSegment

import UIKit

class FuturePriceDaysSegment: UIView {
    
    let daysSegmentControl: UISegmentedControl = {
        let control = UISegmentedControl()
        control.backgroundColor = .clear
        control.tintColor = .clear
        control.setTitleTextAttributes([
            NSAttributedString.Key.font: UIFont.mySFMedium(ofSize: 14) as Any,
            NSAttributedString.Key.foregroundColor: UIColor(red:0.36, green:0.38, blue:0.44, alpha:1)
            ], for: .normal)
        control.setTitleTextAttributes([
            NSAttributedString.Key.font: UIFont.mySFMedium(ofSize: 14) as Any,
            NSAttributedString.Key.foregroundColor: UIColor(red:0.12, green:0.49, blue:0.86, alpha:1)
            ], for: .selected)
        control.translatesAutoresizingMaskIntoConstraints = false
        return control
    }()
    
    let bottomBar: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(red:0.12, green:0.49, blue:0.86, alpha:1)
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    var segmentItems: [String] = ["7 days", "30 days", "90 days", "1 year"] {
        didSet {
            guard segmentItems.count > 0 else { return }
            setupSegmentItems()
            bottomBarWidthAnchor?.isActive = false
            bottomBarWidthAnchor = bottomBar.widthAnchor.constraint(equalTo: daysSegmentControl.widthAnchor, multiplier: 1 / CGFloat(segmentItems.count))
            bottomBarWidthAnchor?.isActive = true
        }
    }
    
    var bottomBarWidthAnchor: NSLayoutConstraint?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    
    private func setup() {
        addSubview(daysSegmentControl)
        addSubview(bottomBar)
        
        daysSegmentControl.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
        daysSegmentControl.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        daysSegmentControl.topAnchor.constraint(equalTo: topAnchor).isActive = true
        daysSegmentControl.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        daysSegmentControl.addTarget(self, action: #selector(segmentedControlValueChanged(_:)), for: .valueChanged)
        
        bottomBar.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        bottomBar.heightAnchor.constraint(equalToConstant: 2).isActive = true
        bottomBar.leftAnchor.constraint(equalTo: daysSegmentControl.leftAnchor).isActive = true
        bottomBarWidthAnchor = bottomBar.widthAnchor.constraint(equalTo: daysSegmentControl.widthAnchor, multiplier: 1 / CGFloat(segmentItems.count))
        bottomBarWidthAnchor?.isActive = true
        
        setupSegmentItems()
    }
    
    private func setupSegmentItems() {
        for (index, value) in segmentItems.enumerated() {
            daysSegmentControl.insertSegment(withTitle: value, at: index, animated: true)
        }
        daysSegmentControl.selectedSegmentIndex = 0
    }
    
    @objc func segmentedControlValueChanged(_ sender: UISegmentedControl) {
        UIView.animate(withDuration: 0.3) {
            let originX = (self.daysSegmentControl.frame.width / CGFloat(self.segmentItems.count)) * CGFloat(self.daysSegmentControl.selectedSegmentIndex)
            self.bottomBar.frame.origin.x = originX
        }
    }
}

Implementation Sample

...
view.addSubview(sampleSegment)

sampleSegment.heightAnchor.constraint(equalToConstant: 45).isActive = true
sampleSegment.topAnchor.constraint(equalTo: someView.bottomAnchor, constant: 5).isActive = true
sampleSegment.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
sampleSegment.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

Check it out:

https://gph.is/2RwAIgq

@hazelf42

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment