Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 13 Segmented Control: Remove swipe gesture to select segment

TLDR: How to remove the swipe/pan gesture recognizer for UISegmentedControl on iOS 13?

Hi, on iOS 13, lots changed with UISegmentedControl. Mostly, the changes were appearance-based. But there is another functionality change that is messing up my app.

On iOS 13, with UISegmentedControls, you can now swipe/pan to change the selected segment in addition to touching the segment you would like to select.

In my app, I basically have a UISegmentedControl embedded in a scrollview. The UISegmentedControl is too long for the screen to display all of the values, so I created a scrollview that is the width of the screen, whose content width is the length of the UISegmentedControl, and to access the non-visible segments, the user swipes the "scrollview" and the segmented control slides.

This worked perfectly up until iOS 13, and now, the user can't scroll the horizontal background scrollview while dragging on the segmented control because I am assuming the scrollview scroll recognizer is overridden by the new scrollview swipe to select gesture.

I have tried even removing ALL gesture recognizers for the UISegmentedControl and all of its subviews recursively, and the swipe to change selection gesture still works... I am stuck.

Thanks, let me know if the problem is unclear

like image 644
ellek Avatar asked Oct 01 '19 01:10

ellek


2 Answers

I have a similar setup (UISegmentedControl inside a UIScrollView bc it's too long and the client didn't want to compress the content to fit). This worked for me (Built on Xcode 11.1):

class NoSwipeSegmentedControl: UISegmentedControl {

    override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

Then set the class of my UISegmentedControl to that. In my app this only prevents the swipe-to-select gesture on UISegmentedControl objects embedded within a UIScrollView. If it is not in a UIScrollView nothing behaves any differently. Which makes sense because gestureRecognizerShouldBegin() returns true by default. So why this allows the UIScrollView to take priority on the swipe gesture, I have no idea. But hope it helps.

like image 75
Aystub Avatar answered Sep 24 '22 08:09

Aystub


I upgraded @Aystub's answer. You can only allow UITapGestureRecogniger to select a segment.

class NoSwipeSegmentedControl: UISegmentedControl {
        override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {

            if(gestureRecognizer.isKind(of: UITapGestureRecognizer.self)){
                return false
            }else{
                return true
            }

       }
}
like image 45
mazend Avatar answered Sep 26 '22 08:09

mazend