Search code examples
iosswiftdatepickeruipickerview

Set picker values by tapping anywhere outside of a popup view in iOS


Currently have a popup view which sets 3 picker values by tapping on the SET button: Current SET button
However, I want to remove the SET button altogether, and have the picker values set upon tapping outside of the popup, which in turn hides the popup.

Here is the current code:

    // function for selecting picker values
func pickerDidSet() {
        let focusPeriodChoice = focusPeriodDataSource[pickerView.selectedRow(inComponent: 0)]
        let breakPeriodChoice = breakPeriodDataSource[pickerView.selectedRow(inComponent: 1)]
        let repeatCountChoice = repeatCountDataSource[pickerView.selectedRow(inComponent: 2)]

        persistPickerChoice(focusPeriodChoice, dataType: .focusPeriod)
        persistPickerChoice(breakPeriodChoice, dataType: .breakPeriod)
        persistPickerChoice(repeatCountChoice, dataType: .repeatCount)

        timerSummaryLabel.text = "\(focusPeriodChoice)m • \(breakPeriodChoice)m • \(repeatCountChoice)x"

        UIView.animate(withDuration: 0.2, animations: { self.pickerContainerView.alpha = 0.0 }, completion: { finished in
            self.pickerContainerView.isHidden = true
        })
    }

// Open popup, by tapping gear icon
    @IBAction func openSettings(_ sender: Any) {
        pickerView.selectRow(pickerChoiceIndex(forDataType: .focusPeriod), inComponent: 0, animated: false)
        pickerView.selectRow(pickerChoiceIndex(forDataType: .breakPeriod), inComponent: 1, animated: false)
        pickerView.selectRow(pickerChoiceIndex(forDataType: .repeatCount), inComponent: 2, animated: false)

        self.pickerContainerView.isHidden = false
        UIView.animate(withDuration: 0.2) {
            self.pickerContainerView.alpha = 1.0
        }
    }

// Once pickers have been set, display the summary
private func configureSummaryLabel() {
        let focusPeriodChoice = pickerChoice(forDataType: .focusPeriod)
        let breakPeriodChoice = pickerChoice(forDataType: .breakPeriod)
        let repeatCountChoice = pickerChoice(forDataType: .repeatCount)

        timerSummaryLabel.text = "\(focusPeriodChoice)m • \(breakPeriodChoice)m • \(repeatCountChoice)x"
    }

// Setting the picker “SET” button
private func addPickerSetButton(atX x: CGFloat, centerY: CGFloat) {
        pickerSetButton.frame = CGRect(x: x, y: 0, width: 40, height: 20)
        pickerSetButton.center = CGPoint(x: pickerSetButton.center.x, y: centerY)
        pickerSetButton.setTitle("SET", for: .normal)
        pickerSetButton.setTitleColor(UIColor.white, for: .normal)
        pickerSetButton.setTitleColor(UIColor.darkGray, for: .highlighted)
        pickerSetButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 17)
        pickerSetButton.addTarget(self, action: #selector(pickerDidSet), for: .touchUpInside)
        pickerHeaderView.addSubview(pickerSetButton)
    }

Solution

  • If the Previous Black View is you default view of ViewController then all you need is to implemented below method.

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            // Check that the touched view is your background view
            if touches.first?.view == self.view {
                // Do What Every You want to do
            }
    }
    

    Detail Every ViewController has a default view object. As in your case the black overlay displaying behind your popup seems like the default view of that view controller. If that black overlay is not your default view then create and IBOutlet of that view which is black opacified in color. And then in the above method where you are check that which view is touch check that if touched view is your black view or not. Suppose you black view's IBOutlet is backgroundView then the above check will be something like this.

    if touches.first?.view == self.backgroundView {
        //It means you have touched outside the pop and out side the pop there is only your backgroundView.
        //Here you should do exactly the same which you were doing when `SET` button was clicked.
    
    }