Ios 在同一分段按钮上点击手柄?

Ios 在同一分段按钮上点击手柄?,ios,ios8,uisegmentedcontrol,iboutlet,Ios,Ios8,Uisegmentedcontrol,Iboutlet,我试图处理分段控件上的点击事件,但当再次单击所选按钮时。例如,对于下面已选择Second的屏幕截图,当再次单击Second按钮时,如何处理该操作 我尝试了一个IBOutlet,但它只在值更改时触发。然后我尝试了下面的代码,但同样的事情,它只在值更改时才会触发。在这两种情况下,当选择“秒”时,再次单击“秒”不会触发任何内容。有办法做到这一点吗 segmentedControl.addTarget(self, action: "segementedAnyTap:", forControlEvents

我试图处理分段控件上的点击事件,但当再次单击所选按钮时。例如,对于下面已选择Second的屏幕截图,当再次单击Second按钮时,如何处理该操作

我尝试了一个IBOutlet,但它只在值更改时触发。然后我尝试了下面的代码,但同样的事情,它只在值更改时才会触发。在这两种情况下,当选择“秒”时,再次单击“秒”不会触发任何内容。有办法做到这一点吗

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

在您对问题的评论中,您提到您正在尝试允许用户选择“未读”以显示所有未读邮件,然后让他们再次单击以将所有邮件标记为未读。我建议不要使用段控件,而是添加一个“标记所有未读”按钮,该按钮在选择“未读”段时显示。这将完成您试图添加的功能,同时也让用户清楚地知道,他们有办法将所有内容标记为未读。

这对我来说很有效,向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
}

你可以设置你的应用程序来显示一个来自你的未读段的popover,用一个按钮来显示所有未读段。要放置popover,请使用:

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];

我不太清楚您为什么要尝试实现这一点,但我建议您将UISegmentedControl子类化,并覆盖touchesEnded:withEvent:

现在,每次按下每个分段时,都会调用uicontrol事件TouchUpInside的计划选择器,并且仍然保留UISegmentedControl的默认功能

注意:如果这是段的第一个选择,您需要自行处理,例如保留以前价值的私有财产。如果添加UIControlEventValueChanged的选择器,它还将触发UIControlEventTouchUpInside的选择器,可能会导致一些混乱或错误


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

我认为这可以解决问题:

- (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];
}
添加KVO

例如:

#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

对于具有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...
            }
        }
}

我知道有点晚了,但另一种技术对我很有效

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


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

Great Answer@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
}

我遇到了一种情况,在选择之前我需要段索引,我不希望.valueChanged事件停止触发,因此我提出了这个方法

为UISegmentedControl和override touchesEnded创建子类


你想完成什么?分段控件用于在不同选项之间切换,因此,只有在所选选项更改时才会收到回调。我的分段控件是:全部和未读。当用户点击未读时,它会显示未读记录,但我希望这样,当他们再次点击未读时,它会弹出一个警报,询问他们是否确定是否要将所有记录标记为未读。我不想在导航栏中添加一个额外的按钮来将所有按钮标记为已读,因为导航栏中已经有其他按钮。我想你可以使用瞬时属性来完成你想要的功能。这似乎将彻底改变分段控件的行为,因为所选索引不再被跟踪,这将破坏现有功能。我希望得到一个子视图来存储每个片段的按钮,并将一个动作附加到它。很抱歉,但是您的设计需要更改。段控件不应该有这样的操作。如果你需要在应用程序中执行更多操作,请为其添加更多按钮,这样做没有坏处,但不要尝试以这种方式更改默认行为。我没有位置在导航标题中放置“标记全部读取”按钮。左侧和右侧按钮被其他功能菜单滑块和搜索占据。因此,我试图节省屏幕的房地产,并与现有的空间创新。如果空间是一个问题,考虑使用两个按钮,而不是段控制,即“Butn1”,“Butn2”。当点击按钮2时,更改其颜色和文本,以明确它现在有另一个用途,您将能够选择第二次点击,同时也让用户看到可用的选项。这会触发,但分段控件的my@iAction停止工作。这将停止值更改事件b
我被解雇了。我实际上没有使用你的代码,但[sender selectedSegmentIndex]位给了我几天来一直在寻找的线索!非常感谢。
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
}
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
}