如何从 UIScrollView 窃取触摸? [英] How to steal touches from UIScrollView?

查看:26
本文介绍了如何从 UIScrollView 窃取触摸?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天在我的创作时间,我对如何从 UIScrollView 窃取触摸并立即将它们发送到特定子视图进行了一些非常全面的研究,同时保持滚动视图其余部分的默认行为.考虑在 UITableView 中有一个 UIPickerView.默认行为是,如果您在选择器视图上拖动手指,滚动视图将滚动,而选择器视图将保持不变.

Today on my creative time I did some quite comprehensive research on how to steal touches from a UIScrollView and send them instantly to a specific subview, while maintaining the default behavior for the rest of the scroll view. Consider having a UIPickerView inside of a UITableView. The default behavior is that if you drag your finger over the picker view, the scroll view will scroll and the picker view will remain unchanged.

我尝试的第一件事是覆盖

The first thing I tried was to override

- (BOOL)touchesShouldCancelInContentView:(UIView *)view

并且根本不允许 UIScrollView 取消选择器视图内的触摸.这有效,但它有一个令人不快的副作用.您希望选择器视图立即响应,因此您必须将 delaysContentTouches 设置为 NO.问题是你不希望表格视图的其余部分立即响应,因为如果它这样做,表格视图单元格将始终在滚动开始前突出显示几毫秒.

and simply not allow the UIScrollView to cancel touches inside the picker view. This works, but it has an unpleasant side effect. You would like the picker view to respond immediately and thus you will have to set delaysContentTouches to NO. The problem is that you don't want the rest of the table view to respond immediately, because if it does the table view cell will always get highlighted for a few milliseconds before the scrolling starts.

我尝试的第二件事是覆盖

The second thing I tried was to override

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

因为我读过滚动视图总是返回自身,所以它会从它的子视图窃取"触摸,然后如果它们对滚动视图不感兴趣,然后将它们发送到子视图.然而,这不再是事实.UIScrollView 的 hitTest:withEvent: 的默认实现实际上返回了应该接收触摸的子视图.相反,它使用手势识别器来拦截触摸.

because I had read that the scroll view always returns itself, so that it will "steal" the touches from its subviews and later send them to the subview if they weren't of interest to the scroll view. However, this isn't true anymore. UIScrollView's default implementation of hitTest:withEvent: actually returns the subview that should receive the touch. Instead it uses gesture recognizers to intercept the touches.

所以我尝试的第三件事是实现我自己的手势识别器,如果触摸在选择器视图之外,则导致它失败,否则会成功.然后我将所有滚动视图的手势识别器设置为失败,除非我的手势识别器使用以下代码失败:

So the third thing I attempted was to implement my own gesture recognizer and cause it to fail if the touch was outside of the picker view and otherwise succeed. Then I set all the scroll view's gesture recognizers to fail unless my gesture recognizer failed using the following code:

for (UIGestureRecognizer * gestureRecognizer in self.tableView.gestureRecognizers)
{
    [gestureRecognizer requireGestureRecognizerToFail:myRecognizer];
}

这实际上从滚动视图中窃取了触摸,但选择器视图从未接收到它们.所以我虽然也许我可以使用以下代码发送我的手势识别器接收到的所有触摸:

This does in fact steal the touches from the scroll view, but the picker view never receives them. So I though maybe I could just send all the touches that my gesture recognizer receives using this code:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches)
        [touch.view touchesBegan:touches withEvent:event];
}

以上代码为简化版.我还确保该视图是一个选择器视图(或其子视图之一),并如上所述为手势识别器设置适当的状态.我也对取消、结束和移动做了同样的事情.但是,选择器视图仍然没有响应.

The above code is a simplified version. I also make sure that the view is a picker view (or one of it's subviews) and set the appropriate state for the gesture recognizer as I mentioned above. I also did the same for canceled, ended and moved. However, the picker view was still not responding.

在返回正常工作之前,我还尝试了最后一件事.在我广泛的谷歌搜索中,我读到嵌套的 UIScrollViews 从 3.x 开始就神奇地工作了,所以我尝试将我的选择器视图放在嵌套的 UIScrollView 中并在其上设置以下属性:

I also tried one last thing before returning to my regular work. During my extensive googling I read that nested UIScrollViews just magically worked since 3.x, so I tried putting my picker view inside a nested UIScrollView and set the following properties on it:

scrollView.delaysContentTouches = NO;
scrollView.canCancelContentTouches = NO;

正如人们所期望的那样,外滚动视图对待内滚动视图与对待选择器视图没有任何不同,因此内滚动视图没有收到触摸.我认为这是一个远景,但实施起来很简单,所以我认为值得一试.

As one would expect the outer scroll view didn't treat the inner scroll view any different than it treated the picker view, so the inner scroll view did not receive the touches. I thought that it was a long shot, but it was simple enough to implement, so I thought it was worth to give it a shot.

我所知道的是 UIScrollView 有一个名为 UIScrollViewDelayedTouchesBeganGestureRecognizer 的手势识别器,它拦截触摸并在 150 (?) 毫秒后将它们发送到适当的子视图.我想我应该能够编写一个类似的识别器,导致滚动视图的默认识别器失败,而不是延迟触摸立即将它们发送到选择器视图.因此,如果有人知道如何编写这样的识别器,请告诉我,如果您有任何其他问题的解决方案,也非常欢迎您分享.

What I know is that UIScrollView has a gesture recognizer named UIScrollViewDelayedTouchesBeganGestureRecognizer that intercepts the touches and sends them to the appropriate subview after 150 (?) ms. I'm thinking that I should be able to write a similar recognizer that causes the scroll view's default recognizers to fail and instead of delaying the touches immediately sends them to the picker view. So if anyone knows how to write such a recognizer please let me know and if you have any other solution to the problem, you're very welcome share that as well.

感谢您通读整个问题,即使您不知道答案,您仍然可以对问题进行投票,以便获得更多关注(希望有人能回答).谢谢!:)

Thank you for reading through the whole question and even if you don't know the answer you could still upvote the question so that it gets more attention (hopefully from someone that can answer it). Thanks! :)

推荐答案

有时您必须先提出问题才能找到答案.Dan Ray 遇到了类似的问题,并使用了非常不同的解决方案来解决它.

Sometimes you have to ask the question before you can find the answer. Dan Ray had a similar problem and solved it with a very different solution.

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView* result = [super hitTest:point withEvent:event];

    if ([result.superview isKindOfClass:[UIPickerView class]])
    {
        self.scrollEnabled = NO;
    }
    else 
    {
        self.scrollEnabled = YES;    
    }
    return result;
}

我已经测试了代码,它对我来说也很好用.然而,这并不是真正从滚动视图中窃取触摸,所以如果有人知道如何真正窃取触摸那就太好了.

I've tested the code and it works fine for me as well. However, this is not really stealing touches from the scroll view, so if anyone knows how to actually steal touches that would be great.

来源:UITableView.tableFooterView 内的 UIPickerView 不接收拖动触摸

这篇关于如何从 UIScrollView 窃取触摸?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆