处理同一个分段按钮?

时间:2015-06-14 17:41:06

标签: ios ios8 uisegmentedcontrol iboutlet

我正在尝试处理分段控件上的点击事件,但是再次单击所选按钮时。例如,对于下面已选择“秒”的屏幕截图,如何再次单击“第二个”按钮时如何处理操作?

我尝试了IBOutlet,但只在值发生变化时触发。然后我尝试了下面的代码,但是只有在值发生变化时它才触发。在两种情况下,选择“秒”时,再次单击“秒”不会触发任何内容。有没有办法做到这一点?

segmentedControl.addTarget(self, action: "segementedAnyTap:", forControlEvents: .AllEvents)

enter image description here

10 个答案:

答案 0 :(得分:6)

这适用于我,为UISegmentedControl添加手势识别器

- (void)viewDidLoad
{
  [super viewDidLoad];

  [self.segmentedControl addTarget:self action:@selector(valueChanged:) forControlEvents:UIControlEventValueChanged];
  UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touched:)];
  [self.segmentedControl addGestureRecognizer:tapGesture];
}

- (void)valueChanged:(id)sender
{
  // value change code
}

- (void)touched:(id)sender
{
  // code to check if the segmented controls index has not changed.
  // execute desired functionality
}

答案 1 :(得分:4)

很棒的答案@Sgorbyo,这是它的Swift 3版本:

override func viewDidLoad() {
    super.viewDidLoad()
    let segmentedTapGesture = UITapGestureRecognizer(target: self, action: #selector(onTapGestureSegment(_:)))
    segmentedControl.addGestureRecognizer(segmentedTapGesture)
}

@IBAction func onTapGestureSegment(_ tapGesture: UITapGestureRecognizer) {
    let point = tapGesture.location(in: segmentedControl)
    let segmentSize = tipSegmentedControl.bounds.size.width / CGFloat(segmentedControl.numberOfSegments)
    let touchedSegment = Int(point.x / segmentSize)

    if segmentedControl.selectedSegmentIndex != touchedSegment {
        // Normal behaviour the segment changes
        segmentedControl.selectedSegmentIndex = touchedSegment
    } else {
        // Tap on the already selected segment
        segmentedControl.selectedSegmentIndex = touchedSegment
    }
    onSegment(segmentedControl)
}

@IBAction func onSegment(_ sender: Any) {
// Your segment changed selector
}

答案 2 :(得分:2)

我认为这可以解决问题:

- (void)viewDidLoad {
    [super viewDidLoad];

    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touched:)];
    [self.segmentedControl addGestureRecognizer:tapGesture];
}

- (void) valueChanged:(id) sender {
    // Your segment changed selector
}

- (void) touched:(UITapGestureRecognizer *) tapGesture {
    CGPoint point = [tapGesture locationInView:self.segmentedControl];
    NSUInteger segmentSize = self.segmentedControl.bounds.size.width / self.segmentedControl.numberOfSegments;
    // Warning: If you are using segments not equally sized, you have to adapt the code in the next line
    NSUInteger touchedSegment = point.x / segmentSize;
    if (self.segmentedControl.selectedSegmentIndex != touchedSegment) {
        // Normal behaviour the segment changes
        self.segmentedControl.selectedSegmentIndex = touchedSegment;
    } else {
        // Tap on the already selected segment, I'm switching to No segment selected just to show the effect
        self.segmentedControl.selectedSegmentIndex = UISegmentedControlNoSegment;
    }
    // You have to call your selector because the UIControlEventValueChanged can't work together with UITapGestureRecognizer
    [self valueChanged:self.segmentedControl];
}

答案 3 :(得分:2)

添加KVO观察。

的exaple:

#pragma mark - 

- (void)viewDidLoad {
    [_segmentControl addObserver:self forKeyPath:@"selectedSegmentIndex" options:NSKeyValueObservingOptionInitial context:nil];
}


#pragma mark - KVO

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSLog(@"segment index: %ld", (long)_segmentControl.selectedSegmentIndex);
}

结果:

2015-06-22 12:31:54.155 Location test[27082:13176230] segment index: 0
2015-06-22 12:31:54.740 Location test[27082:13176230] segment index: 0
2015-06-22 12:31:55.821 Location test[27082:13176230] segment index: 1
2015-06-22 12:31:56.529 Location test[27082:13176230] segment index: 1

答案 4 :(得分:1)

我不太确定你为什么试图实现这个目标,但我想建议继承UISegmentedControl并覆盖touchesEnded:withEvent:

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

    [self sendActionsForControlEvents:UIControlEventTouchUpInside];
}

现在,每次按下每个细分时,系统都会调用UIControlEventTouchUpInside的预定选择器,并保持UISegmentedControl的默认功能。

注意:如果这是段的第一个选择(例如保留前一个值的私有属性),则需要自己处理。如果您为UIControlEventValueChanged添加选择器,它也会触发UIControlEventTouchUpInside的选择器,这可能会引起一些混乱或错误。

祝你好运,希望有所帮助。

答案 5 :(得分:1)

我为具有3个选项(“类别”)的分段控件执行以下操作。 _selectedCategory是一个属性NSInteger,用于跟踪当前所选索引的分段控件。点击,如果我发现_selectedCategory与按下的 -(IBAction)categorySelected:(id)sender { if (_selectedCategory == [sender selectedSegmentIndex]) { sender.selectedSegmentIndex = UISegmentedControlNoSegment; // update my model, etc... } else { _selectedCategory = [sender selectedSegmentIndex]; switch (_selectedCategory) { case 0: // do logic... } } } 相同,则按下所选的分段控件并将其关闭。

{{1}}

答案 6 :(得分:0)

在您对自己问题的评论中,您提到了您尝试允许用户选择“未读”的问题。要显示所有未读邮件,请再次单击以将所有邮件标记为未读。我建议不要使用分段控件来添加"标记所有未读" “未读”时出现的按钮'细分已被选中。这将完成您尝试添加的功能,同时还向用户明确说明他们有办法将所有内容标记为未读。

答案 7 :(得分:0)

您可以将应用设置为显示来自未读片段的弹出窗口,其中包含一个按钮,将所有片段显示为未读。要放置弹出窗口,请使用:

CGRect frame = [segmentControl frame];
frame =CGRectMake((frame.size.width/2*butIndex), 0, frame.size.width/2, segmentControl.bounds.size.height);

[popOver presentPopoverFromRect:frame inView:segmentControl permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

答案 8 :(得分:0)

我知道的有点晚了,但另一项对我有用的技术......

在UISegmentedControl的每个段上添加一个背景清晰的UIButton。每个UIButton都可以拥有自己的UIControlEventTouchUpInside事件处理程序 - 它可以更改UISegmentedControl的selectedSegmentIndex。

然后将UISegmentedControl.userInteractionEnabled设置为NO,并删除其UIControlEventValueChanged事件处理程序。

答案 9 :(得分:0)

我遇到一个在选择之前需要段索引的情况,并且我不希望.valueChanged事件停止触发,因此我想出了这一点。

UISegmentedControl创建一个子类并覆盖touchesEnded

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    // Previous selected segment index
    let oldIdx = selectedSegmentIndex

    super.touchesEnded(touches, with: event)

    // New selected segment index
    let newIdx = selectedSegmentIndex

    // If the previously selected segment index is equal to the new one, 
    // then you are tapping on the same segment button.
    // Call a block, delegate method or whatever to notify this
}