如何永久取消选择“分段控制”按钮中的某个段,直到再次单击它为止 [英] How to deselect a segment in Segmented control button permanently till its clicked again

查看:76
本文介绍了如何永久取消选择“分段控制”按钮中的某个段,直到再次单击它为止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 UISegmentedControl ,有4个段。选择它后,它应该保持选择状态。再次单击同一段时,应取消选择
如何实现这个目标?

I have a UISegmentedControl with 4 segments. When it is selected, it should maintain the selected state. When the same segment is clicked again, it should deselect itself. How to achieve this?

推荐答案

仅限 UISegmentedControl 如果选择了未选择的段,则发送操作,您必须继承 UISegmentedControl 以对其触摸处理进行微小更改。我使用这个类:

Since UISegmentedControl only sends an action if a not selected segment is selected, you have to subclass UISegmentedControl to make a tiny change in its touch handling. I use this class:

@implementation MBSegmentedControl

// this sends a value changed event even if we reselect the currently selected segment
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSInteger current = self.selectedSegmentIndex;
    [super touchesBegan:touches withEvent:event];
    if (current == self.selectedSegmentIndex) {
        [self sendActionsForControlEvents:UIControlEventValueChanged];
    }
}

@end

现在即使已经选择了段,您也将获得 UIControlEventValueChanged 事件。只需将当前索引保存在变量中并在操作中进行比较即可。如果两个索引匹配,则必须取消选择触摸的段。

Now you will get UIControlEventValueChanged events even if the segment is already selected. Simply save the current index in a variable and compare it in the action. If the two indexes match you have to unselect the touched segment.

// _selectedSegmentIndex is an instance variable of the view controller

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    _selectedSegmentIndex = self.segment.selectedSegmentIndex;
}

- (IBAction)segmentChanged:(UISegmentedControl *)sender {
    if (sender.selectedSegmentIndex == _selectedSegmentIndex) {
        NSLog(@"Segment %d deselected", sender.selectedSegmentIndex);
        sender.selectedSegmentIndex =  UISegmentedControlNoSegment;
        _selectedSegmentIndex = UISegmentedControlNoSegment;
    }
    else {
        NSLog(@"Segment %d selected", sender.selectedSegmentIndex);
        _selectedSegmentIndex = sender.selectedSegmentIndex;
    }
}






iOS 7改变了UISegmentedControl处理触摸的方式。现在,在 touchesEnded:期间,selectedSegmentIndex已更改。


iOS 7 changed how touches are handled for UISegmentedControl. The selectedSegmentIndex is now changed during touchesEnded:.

因此更新后的子类应如下所示:

So the updated Subclass should look like this:

@implementation MBSegmentedControl

+ (BOOL)isIOS7 {
    static BOOL isIOS7 = NO;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSInteger deviceSystemMajorVersion = [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."] objectAtIndex:0] integerValue];
        if (deviceSystemMajorVersion >= 7) {
            isIOS7 = YES;
        }
        else {
            isIOS7 = NO;
        }
    });
    return isIOS7;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSInteger previousSelectedSegmentIndex = self.selectedSegmentIndex;
    [super touchesBegan:touches withEvent:event];
    if (![[self class] isIOS7]) {
        // before iOS7 the segment is selected in touchesBegan
        if (previousSelectedSegmentIndex == self.selectedSegmentIndex) {
            // if the selectedSegmentIndex before the selection process is equal to the selectedSegmentIndex
            // after the selection process the superclass won't send a UIControlEventValueChanged event.
            // So we have to do this ourselves.
            [self sendActionsForControlEvents:UIControlEventValueChanged];
        }
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSInteger previousSelectedSegmentIndex = self.selectedSegmentIndex;
    [super touchesEnded:touches withEvent:event];
    if ([[self class] isIOS7]) {
        // on iOS7 the segment is selected in touchesEnded
        if (previousSelectedSegmentIndex == self.selectedSegmentIndex) {
            [self sendActionsForControlEvents:UIControlEventValueChanged];
        }
    }
}

@end






Swift 2.2版本,解决了Grzegorz注意到的问题。


Swift 2.2 version, fixed the problem Grzegorz noticed.

class ReselectableSegmentedControl: UISegmentedControl {
    @IBInspectable var allowReselection: Bool = true

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let previousSelectedSegmentIndex = self.selectedSegmentIndex
        super.touchesEnded(touches, withEvent: event)
        if allowReselection && previousSelectedSegmentIndex == self.selectedSegmentIndex {
            if let touch = touches.first {
                let touchLocation = touch.locationInView(self)
                if CGRectContainsPoint(bounds, touchLocation) {
                    self.sendActionsForControlEvents(.ValueChanged)
                }
            }
        }
    }
}






Swift 3.0更改此修复程序如下所示:


Swift 3.0 changes the fix for this to look like the following:

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

        super.touchesEnded(touches, with: event)

        if previousIndex == selectedSegmentIndex {
            let touchLocation = touches.first!.location(in: self)

            if bounds.contains(touchLocation) {
                sendActions(for: .valueChanged)
            }
        }
    }
}

这篇关于如何永久取消选择“分段控制”按钮中的某个段,直到再次单击它为止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆