Прикосновение к UISlider предотвращает прокрутку UIScrollView

У меня есть (вертикальный) UISlider внутри UIScrollview. Я хотел бы иметь возможность изменить значение ползунка и, не поднимая пальца, прокручивать прокрутку влево или вправо.

Желаемое поведение:

Прикоснитесь внутрь вертикального UISlider, а затем перетащите его влево или вправо, чтобы прокрутить прокрутку

Фактическое поведение:

Прикоснитесь вниз по вертикали UISlider, а затем перетащите пальцем влево или вправо, что не вызывает движения в UIScrollview. Прикосновение вниз от UISlider, за которым следует перетаскивание, прокрутит прокрутку в ожидании

UIView имеет свойство, называемое exclusiveTouch, которое похоже на то, что оно может быть связано с моей проблемой. Я попробовал установить его НЕТ, без везения.

Итак, как можно настроить мои UISliders так, чтобы прокрутка под ними отвечала на касания, которые происходят внутри UISliders?

Ответ 1

Вы пробовали подклассификацию UIScrollView и реализацию - (BOOL)touchesShouldCancelInContentView:(UIView *)view? Согласно документации Apple:

// called before scrolling begins if touches have already been delivered to a subview of the scroll view. if it returns NO the touches will continue to be delivered to the subview and scrolling will not occur
// not called if canCancelContentTouches is NO. default returns YES if view isn't a UIControl

Если вы просто вернете NO, если view - ваш UISlider, это может сделать то, что вы хотите, если только UIScrollView прокручивается по горизонтали. Если это не сработает, вам, скорее всего, придется выполнять пользовательскую обработку касания (например, переопределение touchesBegan:withEvent:, touchesChanged:withEvent: и т.д.) Для ваших UIScrollView и UISlider.

Ответ 2

То, что вы видите, - это предполагаемое поведение.

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

Чтобы делать то, что вы пытаетесь сделать, вам придется самому заниматься сенсорным управлением. Передача события обоим вашим представлениям. Вы можете сделать это, выполнив все методы touchesBegan:, touchesMoved: и передав события обоим представлениям. Подробнее об этом подходе можно узнать в документации UIResponder. Другим подходом является обработка событий в UIGestureRecognizer в представлении прокрутки, которое ударяет по ползунку и обновляет значение ползунка с помощью y-delta. Вы можете больше узнать о распознавателях жестов и обработке событий в разделе о распознавателях жестов в Руководстве по обработке событий для iOS.


Примечание:

Перейдите в приложение "Настройки" и переключите переключатель наполовину (например, режим "Режим полета" ), а затем перетащите вниз. Ничего не случится. Остальная часть ОС ведет себя одинаково. Вы уверены, что это взаимодействие, которое вы действительно хотите сделать? Приложения, которые ведут себя по-разному, часто кажутся странными и незнакомыми.

Ответ 3

Ваш вопрос немного смутил меня. Вы говорите вертикальный слайдер - но перетаскиваете влево и вправо?

Если вы хотите прокрутить список прокрутки при перетаскивании UISlider, правильный способ сделать это -

[mySlider addTarget:self action:@selector(sliderMoved:) forControlEvents:UIControlEventValueChanged];

и

- (void) sliderMoved:(UISlider*) slider {
    myScrollView.contentOffset.x = slider.value * (myScrollView.contentSize.width - myScrollView.bounds.size.width);
}

Надеюсь, это то, что вы хотите.

Ответ 4

Вам нужно установить задержекContentTouches как НЕТ и предотвратить прокрутку объектов UISlider, Проверить код ниже.

mySlider.delaysContentTouches = NO;

- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view {
    if ([view isKindOfClass:[UISlider class]])
    {
        UITouch *touchEvent = [[event allTouches] anyObject];
        CGPoint locationEvent = [touchEvent locationInView:view];
        CGRect thumbRect;
        UISlider *mySlide = (UISlider*) view;
        CGRect trackRect = [mySlide trackRectForBounds:mySlide.bounds];
        thumbRect = [mySlide thumbRectForBounds:mySlide.bounds trackRect:trackRect value:mySlide.value];
        if (CGRectContainsPoint(thumbRect, locationEvent))
            return YES;
    }
    return NO;
}

Ответ 5

Я думаю, что вы можете получить некоторую ссылку из этот пример в этом примере показано, что как отменить любое касание или любые распознаватели жестов и применить их к другим представлениям.

Пусть это приведет вас к решению вашей проблемы, и если это просто сообщит мне об этом

Happy Codding:)