Регистр UISegmentedControl касается выбранного сегмента - PullRequest
61 голосов
/ 25 октября 2009

У меня есть сегментированный элемент управления, где пользователь может выбрать, как заказать список. Работает нормально.

Однако мне бы хотелось, чтобы при нажатии на уже выбранный сегмент ордер инвертировался. У меня есть весь код на месте, но я не знаю, как зарегистрировать ответвления в этих сегментах. Кажется, единственное управляющее событие, которое вы можете использовать, это UIControlEventValueChanged, но это не работает (поскольку выбранный сегмент фактически не изменяется).

Есть ли решение для этого? И если да, то что это?

Заранее спасибо!

Ответы [ 19 ]

1 голос
/ 15 января 2015

Ниже кусок кода, который работал для меня. Повторное нажатие на тот же сегмент отменяет его выбор.

@implementation WUUnselectableSegmentedControl
{
    NSUInteger _selectedIndexBeforeTouches;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    _selectedIndexBeforeTouches = self.selectedSegmentIndex;
    [super touchesBegan:touches withEvent:event];
}

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

    if (_selectedIndexBeforeTouches == self.selectedSegmentIndex)
    {
        // Selection didn't change after touch - deselect
        self.selectedSegmentIndex = UISegmentedControlNoSegment;
        [self sendActionsForControlEvents:UIControlEventValueChanged];
    }
}

@end
1 голос
/ 09 февраля 2014

На основании ответа Боба де Граафа:

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

Обратите внимание на использование UIControlEventAllTouchEvents вместо UIControlEventValueChanged.

Также нет необходимости звонить -(void)setSelectedSegmentIndex:.

1 голос
/ 11 апреля 2010

Большая помощь! То, что я хочу сделать, - это установить один или нет установленных кнопок - и когда кнопка установлена, второе нажатие отменяет его Это моя модификация:

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

Сначала уведомить позволяет прочитать элемент управления, чтобы найти текущую настройку до ее сброса.

1 голос
/ 16 января 2019

Похоже, забавный вопрос, чтобы ответить. Эта схема распространяется на решения Стива Е и Йершуачу. Эта версия использует UITapGestureRecognizer для захвата всех касаний и устанавливает selectedSegmentIndex в -1; но он также передает все касания в UISegmentedControl, чтобы он мог обрабатывать любые обычные касания. Подклассы не требуются.

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
}
1 голос
/ 25 октября 2009

Первая идея, которая у меня возникла, - подключить действия Touch Up Inside или Touch Down к вашему методу сортировки, но, похоже, это не сработает.

Вторая идея - это скорее обходной путь, установите свойство Momentary в сегментированном элементе управления. Затем он будет запускать действие Value Did Change при каждом нажатии.

1 голос
/ 20 августа 2016

iOS 9 решение. Переопределите UISegmentedControl с таким классом:

@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 голосов
/ 27 ноября 2018

Это должно работать:

- (IBAction)segmentedControlValueChanged:(id)sender
{
    UISegmentedControl *sc = (UISegmentedControl*) sender;
    switch ([sc selectedSegmentIndex])
    {
       case 0:
            NSLog(@"First option!");
            break;
       case 1:
            NSLog(@"Second option!");
            break;
       case UISegmentedControlNoSegment:
            NSLog(@"No option...");
            break;
        default:
            NSLog(@"No selected option :( ");
    }

    //this resets the segmented control (mySC) value to act as a button.
    [self.mySC setSelectedSegmentIndex:UISegmentedControlNoSegment];
}

Не забудьте подключить это IBAction к вашей сегментированной управляющей розетке Value Changed в Инспекторе соединений .

0 голосов
/ 19 мая 2015

Я использую KVO для инвертирования уже выбранного сегмента для iOS8.

#import "QCSegmentedControl.h"

static void *QCSegmentedControlContext = &QCSegmentedControlContext;

@implementation QCSegmentedControl

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self registerKVO];
    }

    return self;
}

- (void)dealloc {
    [self removeObserver:self forKeyPath:@"selectedSegmentIndex"];
}

#pragma mark -

- (void)registerKVO {
    [self addObserver:self
           forKeyPath:@"selectedSegmentIndex"
              options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
              context:QCSegmentedControlContext];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    if (context == QCSegmentedControlContext) {
        NSNumber *new = change[NSKeyValueChangeNewKey];
        NSNumber *old = change[NSKeyValueChangeOldKey];
        if (new.integerValue == old.integerValue) {
            self.selectedSegmentIndex = UISegmentedControlNoSegment;
        }
    }
}

@end
0 голосов
/ 02 сентября 2015

Решение с выбранным ответом не работало для меня с текущей версией iOS v8.x. Но @Andy предложит решение, и я закончу:

Подкласс UISegmentedControl и метод перезаписи touchesEnded в подклассе:

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

В классе, где вы собираетесь использовать UISegmentedControl, создайте iVar currentSelectedSegIndex. Добавьте UIControlEventAllTouchEvents рядом с вашими методами действий UIControlEventValueChanged:

NSInteger currentSelectedSegIndex;

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

Реализуйте два метода действия:

-(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
}
...