UISegmentedControl register taps on selected segment

后端 未结 20 2876
渐次进展
渐次进展 2020-12-04 15:28

I have a segmented control where the user can select how to order a list. Works fine.

However, I would like that when an already selected segment is tapped, the orde

相关标签:
20条回答
  • 2020-12-04 15:52

    Based on Bob de Graaf's answer:

    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [self sendActionsForControlEvents:UIControlEventAllTouchEvents];
        [super touchesEnded:touches withEvent:event];
    }
    

    Note the use of UIControlEventAllTouchEvents instead of UIControlEventValueChanged.

    Also there's no need to call -(void)setSelectedSegmentIndex:.

    0 讨论(0)
  • 2020-12-04 15:52

    Seems like a fun question to answer. This scheme expands upon Steve E's and yershuachu's solutions. This version uses a UITapGestureRecognizer to capture all touches and which sets the selectedSegmentIndex to -1; but it also passes on all touches to the UISegmentedControl so it can handle any normal touches. No subclassing is required.

    UISegmentedControl *mySegControl;
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        [mySegControl addTarget:self action:@selector(segmentAction:)
               forControlEvents:UIControlEventValueChanged];
        // allow the a seg button tap to be seen even if already selected
        UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
                                              initWithTarget:self action:@selector(unitsSegTap:)];
        tapGesture.cancelsTouchesInView = NO; // pass touches through for normal taps
        [mySegControl addGestureRecognizer:tapGesture];
    
        // continue setup ...
    }
    
    - (void)segTap:(UITapGestureRecognizer *)sender
    {
        mySegControl.selectedSegmentIndex = -1;
    }
    
    // called for UIControlEventValueChanged
    - (void)segmentAction:(UISegmentedControl *)sender
    {
        NSInteger index = sender.selectedSegmentIndex;
        NSLog(@"unitsSegmentAction %d",(int)index);
        // process the segment
    }
    
    0 讨论(0)
  • 2020-12-04 15:53

    Big help! What I want to do is have the option of one or no buttons set - and when a button is set, a second tap unsets it. This is my modification:

    - (void)setSelectedSegmentIndex:(NSInteger)toValue
    {
      // Trigger UIControlEventValueChanged even when re-tapping the selected segment.
      if (toValue==self.selectedSegmentIndex) {
        [super setSelectedSegmentIndex:UISegmentedControlNoSegment]; // notify first
        [self sendActionsForControlEvents:UIControlEventValueChanged]; // then unset
      } else {
        [super setSelectedSegmentIndex:toValue]; 
      }
    }
    

    Notify first lets you read the control to find the current setting before it's reset.

    0 讨论(0)
  • 2020-12-04 15:54

    The selected answer's solution did not work for me as of current iOS v8.x. But @Andy offer a solution and I will complete:

    Subclass the UISegmentedControl, and overwrite touchesEnded method in the subclass:

    -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [self sendActionsForControlEvents:UIControlEventAllTouchEvents];
        [super touchesEnded:touches withEvent:event];
    }
    

    In the class where you intend to use the UISegmentedControl, create an iVar currentSelectedSegIndex. Add the UIControlEventAllTouchEvents beside your UIControlEventValueChanged action methods:

    NSInteger currentSelectedSegIndex;
    
    [aSegmentedController addTarget:self action:@selector(aSegmentedControllerSelection:) forControlEvents:UIControlEventValueChanged];
    [aSegmentedController addTarget:self action:@selector(aSegmentedControllerAllTouchEvent:) forControlEvents:UIControlEventAllTouchEvents];
    

    Implement the two action methods:

    -(void)aSegmentedControllerAllTouchEvent:(MyUISegmentedControl *)seg
    {
        seg.selectedSegmentIndex = UISegmentedControlNoSegment;
    }
    -(void)aSegmentedControllerSelection:(MyUISegmentedControl *)seg
    {
        if (currentSelectedSegIndex == seg.selectedSegmentIndex)
        {
            seg.selectedSegmentIndex = UISegmentedControlNoSegment;
            currentSelectedSegIndex = NSIntegerMax;
            NSLog(@"%s Deselected.", __PRETTY_FUNCTION__);
            // do your stuff if deselected
            return;
        }
        NSLog(@"%s Selected index:%u", __PRETTY_FUNCTION__, seg.selectedSegmentIndex);
        currentSelectedSegIndex = seg.selectedSegmentIndex;
        //do your stuff if selected index
    }
    
    0 讨论(0)
  • 2020-12-04 15:55

    iOS 9 solution. Override UISegmentedControl with such class:

    @interface SegmentedControl()
    
    @property (nonatomic) NSInteger previousCurrent;
    
    @end
    
    @implementation SegmentedControl
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        self.previousCurrent = self.selectedSegmentIndex;
        [super touchesBegan:touches withEvent:event];
    }
    
    - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        [super touchesEnded:touches withEvent:event];
    
        if (self.selectedSegmentIndex == self.previousCurrent) {
            [self sendActionsForControlEvents:UIControlEventValueChanged];
        }
    
        self.previousCurrent = NSNotFound;
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-04 15:58

    This works on both iOS 4 and 5:

    -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
      int oldValue = self.selectedSegmentIndex;
      [super touchesBegan:touches withEvent:event];
      if ( oldValue == self.selectedSegmentIndex )
        [self sendActionsForControlEvents:UIControlEventValueChanged];
    }
    
    0 讨论(0)
提交回复
热议问题