bhartsb
bhartsb

Reputation: 1366

UISegmentedControl unselect segment by pressing it again

How can one unselect a given segment in a UISegmented control, by pressing the same segment again?

E.g. Press segment 0, it becomes selected and remains highlighted. Press segment 0 again and it becomes unselected and unhighlighted.

The control only fires UIControlEventValueChanged events. Other events don't seem to work with it.

There is a property 'momentary' which when set to YES almost allows the above behavior, excepting that highlighting is only momentary. When momentary=YES pressing the same segment twice results in two UIControlEventValueChanged events, but when momentary=NO only the first press of a given segment results in a UIControlEventValueChanged event being fired. I.e. subsequent presses on the same segment will not fire the UIControlEventValueChanged event.

Upvotes: 4

Views: 4143

Answers (4)

Zaphod
Zaphod

Reputation: 7250

Based on @protspace answer, a simpler way, without having to write anything in the @IBAction:

class DeselectableSegmentedControl: UISegmentedControl {
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        let previousSelectedSegmentIndex = selectedSegmentIndex

        super.touchesEnded(touches, with: event)

        if previousSelectedSegmentIndex == selectedSegmentIndex {
            let touch = touches.first!
            let touchLocation = touch.location(in: self)
            if bounds.contains(touchLocation) {
                selectedSegmentIndex = UISegmentedControl.noSegment
                sendActions(for: .valueChanged)
            }
        }
    }
}

Upvotes: 0

Chameleon
Chameleon

Reputation: 1608

Not EXACTLY what you ask for but I was searching for a similar feature and decided on this.

Add doubleTap gesture to UISegmentedControl that sets the selectedSegmentIndex

When you initialize your UISegmentedControl.

let doubleTap = UITapGestureRecognizer(target: self, action #selector(YourViewController.doubleTapToggle))
doubleTap.numberOfTapsRequired = 2
yourSegmentedControl.addGestureRecognizer(doubleTap)

Function to deselect segment

@objc func doubleTapToggle () {
    yourSegmentedControl.selectedSegmentIndex = -1
    yourSegmentedControl.sendActions(for: valueChanged)
}

Upvotes: 0

protspace
protspace

Reputation: 2147

you can subclass UISegmentedControl:

Swift 3

class ReselectableSegmentedControl: UISegmentedControl {

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let previousSelectedSegmentIndex = self.selectedSegmentIndex

        super.touchesEnded(touches, withEvent: event)

        if previousSelectedSegmentIndex == self.selectedSegmentIndex {
            if let touch = touches.first {
                let touchLocation = touch.locationInView(self)
                if CGRectContainsPoint(bounds, touchLocation) {
                    self.sendActionsForControlEvents(.ValueChanged)
                }
            }
        }
    }


}

Swift 4

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    let previousSelectedSegmentIndex = self.selectedSegmentIndex

    super.touchesEnded(touches, with: event)

    if previousSelectedSegmentIndex == self.selectedSegmentIndex {
        let touch = touches.first!
        let touchLocation = touch.location(in: self)
        if bounds.contains(touchLocation) {
            self.sendActions(for: .valueChanged)
        }
    }
}

and then

 @IBAction func segmentChanged(sender: UISegmentedControl) {
    if (sender.selectedSegmentIndex == selectedSegmentIndex) {
        sender.selectedSegmentIndex =  UISegmentedControlNoSegment;
        selectedSegmentIndex = UISegmentedControlNoSegment;
    }
    else {
        selectedSegmentIndex = sender.selectedSegmentIndex;
    }
}

Upvotes: 10

Tom Daniel
Tom Daniel

Reputation: 323

UISegmentedControl can be programmatically deselected with Swift using @IBOutlet weak var mySegmentedControl: UISegmentedControl! and mySegmentedControl.selectedSegmentIndex = -1. As far as detecting the touch of the segment, I do not know. Hopefully someone else will have that answer.

Upvotes: -1

Related Questions