UISlider 和 UIScrollView
我有一个 UISlider
作为视图的一部分,该视图加载到启用了分页的 UIScrollView
中。我注意到一个意想不到的行为。如果用户尝试快速使用滑块(即按下并移动),它将“激活”滚动视图,导致页面切换。但是,如果您按住一秒钟,滑块就会“激活”,然后您就可以调整滑块值。这种行为是不可取的。
当加载到 UIScrollView
中时,使 UISlider
做出响应的最佳方法是什么?我考虑过添加一个“拦截器”视图,该视图只会占用滑块下方的触摸事件,但不确定这是否是最好的方法。
I have a UISlider
as part of a view that is loaded into a UIScrollView
with paging enabled. I've noticed an unexpected behavior. If the user tries to use the slider quickly (i.e. press and move) it "activates" the scroll view, causing the page to switch. However, if your press and hold for a second the slider "activates" and you can then adjust the slider value. This behavior is undesirable.
What is the best way to make the UISlider
responsive when loaded into a UIScrollView
? I've thought about adding a "blocker" view that just eats up touch events that is placed under the slider, but not sure if this is the best way to go about it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
无需在
UIScrollView
端进行命中测试。因为延迟是由 UIScrollView 本身设置的。子类化和实现自定义hitTest:withEvent:
不会有帮助,因为它仍然会延迟触发。我花了几个小时寻找一个优雅的解决方案,因为我想在 ios 应用程序切换器中模拟苹果自己的volumeslider。
窍门:
不幸的是,这会禁用
UISliders
轨道上的事件,因此对于这部分,您的UIScrollView
不会触发任何触摸事件,因为它们首先被滑块捕获。要传递除
UISliders
拇指矩形中的触摸事件以外的触摸事件,您必须子类化UISlider
并添加以下内容:there's no need for a hit test on the
UIScrollView
side. since the delay is set by theUIScrollView
itself. subclassing and implementing a customhitTest:withEvent:
won't help since it's still triggered with delay.i searched hours for an elegant solution to this, since i wanted to simulate apple's own volumeslider in the ios application switcher.
the trick:
unfortunately this disables events along the
UISliders
track, so for this part yourUIScrollView
won't trigger any touchevents because they are caught by the slider first.to pass touchevents other than those which are in the
UISliders
thumb rect you have to subclassUISlider
and add the following:让您的滚动视图检测滑块占据的区域上的触摸(覆盖
hitTest:withEvent:
,您可能需要子类UIScrollView
)。如果检测到对所述区域的触摸,请告诉您的滚动视图立即将触摸传递到滑块。Have your scroll view detect touches over the region occupied by your slider (override
hitTest:withEvent:
, you may need to subclassUIScrollView
). If a touch over said region is detected, tell your scroll view to immediately pass the touch to the slider.在创建音频播放器时,我遇到了
sliderView
的确切问题,并将其添加到scrollView
中,每当我触摸sliderView
时,scrollView
用于获取触摸,而不是sliderView
,而是scrollView
moving 。为了避免这种情况,当用户触摸sliderView
时,我禁用了scrollView
的 srcolling,否则启用滚动。While creating an audio player I had the exact problem with a
sliderView
and it is added to ascrollView
, and whenever I touched thesliderView
, thescrollView
used to get the touch and instead of thesliderView
, thescrollView
moved . To avoid this , I disabled the srcolling of thescrollView
when the user touched thesliderView
and otherwise the scrolling is enabled .我的问题是这个问题的超集 - 我在 UITableViewCells 中有 UISliders,整个 UITableView 是 UIScrollView 中的一个页面。滑块对与其他两个的交互造成了严重破坏,并且子类化解决方案不起作用。这是我想出的效果很好的方法:当滑块移动时发送通知,并在此期间启用 UITableView 和 UIScrollView 禁用滚动。请注意下图中:我的滑块是水平的,我的 tableview 是垂直的,我的 UIScrollView 有水平页面。

UITableViewCell 为以编程方式创建的滑块拾取事件:
出于本教程的目的,我们只关心 touchDown 和 Up:
现在,我们在 UITableView(请注意,tableview 在 VC 中,但我确信如果您子类化的话这会起作用)
和 UIScrollView(与上面相同,附在 VC 中):
我很想听到一个更优雅的解决方案,但这绝对可以完成工作。当您使用滑块时,表格和滚动视图保持静止,当您在滑块外部单击时,表格视图和滚动视图将按预期移动。另请注意,我可以在此解决方案中使用所有 3 个组件的非子类实例。希望这对某人有帮助!
My problem was a superset of this issue - I've got UISliders inside UITableViewCells and the whole UITableView is a page inside a UIScrollView. The sliders were wreaking havoc on the interactions with the other two and the subclassing solutions did not work. Here's what I came up with that's working great: send notifications when the sliders move and have the UITableView and UIScrollView disableScrolling on during this time. Note in the picture below: my sliders are horizontal, my tableview is vertical, and my UIScrollView has horizontal pages.

The UITableViewCell picks up events for the programmatically-created slider:
For the purposes of this tutorial, we only care about touchDown and Up:
Now, we catch in these notifications in both the UITableView (note that the tableview is in a VC but I'm sure this would work if you subclassed):
and the UIScrollView (same as above, enclosed in a VC):
I'd love to hear a more elegant solution, but this one definitely gets the job done. When you use a slider, the table and scrollviews hold still and when you click outside the sliders, the tableview and scrollviews move as expected. Also - notice that I could use non-subclassed instances of all 3 components in this solution. Hope this helps someone!
我想将此作为评论发布,但我的帐户没有代表,所以我不得不发布完整的答案。 user762391 的答案包括 hitTest 覆盖,效果非常好。我只是想补充一点,您可以像这样覆盖 pointInside:withEvent: ,而不是覆盖 hitTest: (保留拇指矩形方法):
或在 Swift 中:
I wanted to post this as a comment, but my account has no rep so I had to post a whole answer. user762391's answer including the hitTest override works perfectly. I just want to add that instead of overriding hitTest, you could instead override pointInside:withEvent: like this (keeping the thumbRect method):
or in Swift:
Swift 3 中获得最多支持的评论代码:)
most upvoted comment code in Swift 3 :)
您可以子类化 UIScrollView 并重写方法
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
如下:同时设置
yourScrollView.滚动视图的delaysContentTouches = NO;
属性。You can subclass UIScrollView and override the method
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
as follows:Also Set
yourScrollView.delaysContentTouches = NO;
property for the scrollview.