Search code examples
iosswiftuisegmentedcontrol

How do I change what is shown when the UISegmentedControl index is changed?


I have a small issue with my segmented controller and trying to change the views shown to the user when clicking a new index. I have code set to show text-boxes that the user would type into when the index is changed. One issue is that I want to place text-boxes under the segmented controller evenly and the other issue is that when I click a new index in the controller, the prior text box is still on the screen, but I need it to show just the text box correlating to the specific index that is chosen. The code is shown below where I created the segment controller and handled the switch of indexes as well as the creation of the text-boxes.

    let segmentedControl: UISegmentedControl = {
        let sc = UISegmentedControl(items: ["Inventory", "Sale", "Expense"])
        sc.selectedSegmentIndex = 0
        sc.layer.cornerRadius = 9
        sc.layer.borderWidth = 1
        sc.layer.borderColor = UIColor.lightGray.cgColor
        sc.layer.masksToBounds = true

        sc.addTarget(self, action: #selector(handleSegmentChange), for: .valueChanged)
        return sc
    }()

    //function to handle click of segmented control buttons
    @objc fileprivate func handleSegmentChange(sender: UISegmentedControl){
        print(segmentedControl.selectedSegmentIndex)

        switch segmentedControl.selectedSegmentIndex{
        case 0:
            view.addSubview(myProduct)
        case 1:
            view.addSubview(myRetail)
        default:
            view.addSubview(myExpense)
            break
        }

    }

    let myProduct : UITextField = {
        let mp = UITextField(frame: CGRect(x: 10, y: 320, width: 300, height: 10))
        mp.placeholder = "Enter Product name"
        mp.borderStyle = UITextField.BorderStyle.line
        mp.backgroundColor = .white
        mp.textColor = .cyan

        return mp
        }();

    let myRetail : UITextField = {
        let mp = UITextField(frame: CGRect(x: 10, y: 320, width: 300, height: 20))
        mp.placeholder = "Enter Retail price"
        mp.borderStyle = UITextField.BorderStyle.line
        mp.backgroundColor = .white
        mp.textColor = .cyan

        return mp
        }();

    let myExpense : UITextField = {
        let mp = UITextField(frame: CGRect(x: 10, y: 320, width: 300, height: 30))
        mp.placeholder = "Enter Expense name"
        mp.borderStyle = UITextField.BorderStyle.line
        mp.backgroundColor = .white
        mp.textColor = .cyan

        return mp
        }();

Most of the solutions I have seen are outdated, which is why I am posting my own version here. Thanks in advance for help anyone can provide.


Solution

  • You can set tag for each UITextField as below,

    let myProduct : UITextField = {
        let mp = UITextField(frame: CGRect(x: 10, y: 320, width: 300, height: 10))
        mp.placeholder = "Enter Product name"
        mp.borderStyle = UITextField.BorderStyle.line
        mp.backgroundColor = .white
        mp.textColor = .cyan
        mp.tag = 11
        return mp
    }()
    
    let myRetail : UITextField = {
        let mp = UITextField(frame: CGRect(x: 10, y: 320, width: 300, height: 20))
        mp.placeholder = "Enter Retail price"
        mp.borderStyle = UITextField.BorderStyle.line
        mp.backgroundColor = .white
        mp.textColor = .cyan
        mp.tag = 12
        return mp
    }()
    
    let myExpense : UITextField = {
        let mp = UITextField(frame: CGRect(x: 10, y: 320, width: 300, height: 30))
        mp.placeholder = "Enter Expense name"
        mp.borderStyle = UITextField.BorderStyle.line
        mp.backgroundColor = .white
        mp.textColor = .cyan
        mp.tag = 13
        return mp
    }()
    

    and then inside handleSegmentChange, remove any view with that tag before adding a new one as below,

    //function to handle click of segmented control buttons
    @objc fileprivate func handleSegmentChange(sender: UISegmentedControl){
        print(segmentedControl.selectedSegmentIndex)
    
        [11, 12, 13].forEach { self.view.viewWithTag($0)?.removeFromSuperview() }
    
        switch segmentedControl.selectedSegmentIndex {
        case 0:
            view.addSubview(myProduct)
        case 1:
            view.addSubview(myRetail)
        default:
            view.addSubview(myExpense)
        }
    }
    

    For the position issue, you haven't set any frame to UISegmentControl. You can set frame as below to get the result shown,

    let segmentedControl: UISegmentedControl = {
        let sc = UISegmentedControl(items: ["Inventory", "Sale", "Expense"])
        sc.selectedSegmentIndex = 0
        sc.layer.cornerRadius = 9
        sc.layer.borderWidth = 1
        sc.layer.borderColor = UIColor.lightGray.cgColor
        sc.layer.masksToBounds = true
        sc.frame = CGRect(origin: CGPoint(x: 10, y: 280), size: CGSize(width: 300, height: 30))
    
        sc.addTarget(self, action: #selector(handleSegmentChange), for: .valueChanged)
        return sc
    }()
    

    enter image description here