触摸UISlider会阻止UIScrollView的滚动

11

我有一个垂直的UISlider在UIScrollview内。我想能够更改滑块的值,并且在不抬起手指的情况下左右滚动滚动视图。

期望的行为:

在垂直UISlider内部按下后,紧接着向左或向右拖动手指会导致滚动视图滚动

实际行为:

在垂直UISlider内部按下后,紧接着向左或向右拖动手指不会导致UIScrollview中的任何移动。在垂直UISlider外部按下并拖动会按预期滚动滚动视图。

UIView有一个称为exclusiveTouch的属性,似乎与我的问题相关。但我尝试将它设置为NO,但没有成功。

那么,我该如何设置我的UISlider,以便位于其下面的滚动视图对源自UISlider内部的触摸作出反应?


5
期望/预期结果与实际结果相符,应该给予加1分。更多的问题应该这样做。 - David Rönnqvist
5个回答

5

你尝试过通过子类化 UIScrollView 并实现 - (BOOL)touchesShouldCancelInContentView:(UIView *)view 吗?据苹果文档所述:

// 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

如果您的视图是UISlider,只需返回NO,并且您的UIScrollView只水平滚动,那么这可能会实现您想要的效果。如果这不起作用,您可能需要对您的UIScrollViewUISlider进行自定义触摸处理(例如重写touchesBegan:withEvent:touchesChanged:withEvent:等)。

2
你所看到的是预期行为。
每个触摸事件只能被一个控件处理。`exclusiveTouch` 的作用实际上是防止其他触摸事件传递到其他视图。
要做你正在尝试的事情,你需要自己处理一些触摸事件。将事件传递给你的两个视图之一。你可以通过实现所有的 `touchesBegan:`、`touchesMoved:` 等方法并将事件传递给两个视图来实现。你可以在 UIResponder documentation 中了解更多关于这种方法的信息。另一种方法是在命中滚动视图的滑块上使用 UIGestureRecognizer 进行事件处理,并使用 y-增量更新滑块的值。你可以在 iOS 事件处理指南中有关手势识别器的部分 中了解更多关于手势识别器和事件处理的信息。
侧注:

打开“设置”应用程序,切换一个开关到一半(例如飞行模式切换),然后向下拖动。什么都不会发生。操作系统的其余部分表现方式相同。你确定这是你真正想要做的交互吗?表现不同的应用程序通常会感觉奇怪和陌生。


要做你想做的事情,你必须自己处理一些触摸操作。 - morgancodes
@morgancodes 是的,可能有点含糊。我添加了两个基本替代方案和相关文档的链接,以便了解如何处理自己的触摸操作。 - David Rönnqvist

1

你需要将delaysContentTouches设置为NO,并防止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;
}

1

您的问题让我有些困惑。您是说垂直滑块 - 但是左右拖动?

如果您希望在拖动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);
}

希望这是你想要的。


谢谢您的回复,但这不是我要问的。我正在尝试弄清楚如何使touchesMoved事件适用于UIScrollview,而不仅仅是滚动视图内的UISlider。我希望垂直拖动可以更改滑块的值,而水平拖动可以更改UIScrollview的位置,就像没有垂直滑块一样。 - morgancodes

0

我认为你可以从this的例子中获得一些参考。在这个例子中,展示了如何取消任何触摸或手势识别器并将它们应用于其他视图。

希望这能帮助你解决问题,如果有帮助,请告诉我。

祝编码愉快 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接