【问题标题】:UIScrollView sending touches to subviewsUIScrollView 向子视图发送触摸
【发布时间】:2012-08-10 11:29:33
【问题描述】:

注意:我已经阅读了一些关于UIScrollView 向子视图发送触摸的问题(包括this,虽然我已经投了赞成票,但它不再像我预期的那样工作了)。

我有什么:我有一个UIScrollView,里面有一个自定义UIView(我们称之为A),里面覆盖了整个UIScrollView。我还可以将其他自定义 UIViews 放在 A 内。

关于我正在执行的代码:

[scrollView setDelaysContentTouches:YES];
scrollView.canCancelContentTouches = NO;

发生了什么: 目前我唯一的问题是,如果我想在 A 内移动子视图,我必须触摸它,等待,然后移动它。正如here所说的那样:

现在,行为会根据 首先触摸 UIView。如果它很短,那么相对拖动 被管理,因为它是 UIScrollView 的滚动。如果长的话 我正在 UIView 中获取 touchesMoved: 事件。

我想要什么: A 中的子视图应该始终获得优先权,我不应该触摸和等待。如果我触摸 A 而不是它的子视图,我希望 UIScrollView 接收触摸,例如平移和移动(contentSize 大于 frame)。


编辑 1.0

我在通用 UIScrollView 中拥有这个 A 视图的唯一原因是因为我希望能够放大/缩小 A 视图.所以我正在做以下事情:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return customView; // this is the A view
}

一开始我在UIScrollView 中没有A 视图,我唯一做的就是将A 添加为我的@987654336 的子视图@root 视图,一切顺利。 如果有其他方法可以启用放大/缩小,我很乐意接受答案。

【问题讨论】:

  • 只是快速谷歌搜索,试图覆盖scrollView的hitTestherbert-siojo.com/2011/04/01/…
  • 已经看到这个建议,不起作用。
  • 您是否尝试将 UIGestureRecognizer 添加到滚动视图,然后检查触摸是否 locationInView 在自定义 uiview ...
  • A 视图覆盖了整个屏幕。所以总是会返回 A 屏幕。

标签: iphone ios ipad uiview uiscrollview


【解决方案1】:

Jacky,我需要一个类似的东西:在一个建筑计划中(你的 A,在我的例子中是 UIScrollView 的一个子类),让用户放置和调整对象的大小(称为 Bs)。以下是我对这种行为的理解:

  • 在superview的(A)initWithFrame:方法中,设置这两个:

    self.canCancelContentTouches = YES;
    self.delaysContentTouches = NO;
    

    这将确保 B 上的分接头立即路由到 B。

  • 在嵌入的B中,阻止superview A取消点击,这样它就不会干扰在B上启动的手势。

    touchesBegan: 方法中,向上搜索视图层次结构(使用视图的superview 属性)直到找到UIScrollView,并将其canCancelContentTouches 设置为NO。记住你改变的superview,在B的touchesEndedtouchesCancelled方法中恢复这个属性。

我很想知道这是否也适合你。祝你好运!

诺比

【讨论】:

  • 我以前也有过,而且效果很好。问题是我想用平移手势启用放大/缩小...为此我需要放 A 在 UIScrollView 中查看,因此我可以调用此方法:- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
【解决方案2】:

我认为您最好使用“touchesBegan,touchesMoved,touchesEnded”来传递事件。

你可以这样做:

你应该做一个 mainView 。它有2个属性。一个是 yourScrollView A ,一个是 yourCustomView。

`[yourScrollView addSubviews:yourCustomView];
[mainView addSubviews:yourScrollView];`

然后像这样在 mainView.m 中编写你的 touches 方法(忽略 scrollView 语句)

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

    UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
   if ([[touches allObjects] isKindOfClass:[yourCustomView class]]) 
   {

        //do whatever you want
   }

}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

    UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
   if ([[touches allObjects] isKindOfClass:[yourCustomView class]]) 
   {
       //do whatever you want
   }
}

最后一步:将事件传递给scrollView(你的A)的子视图。

#import "yourScrollView.h"


@implementation yourScrollView


- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code.
    }
    return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    if(!self.dragging)
        [[self nextResponder] touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesMoved:touches withEvent:event];
    if(!self.dragging)
        [[self nextResponder] touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesEnded:touches withEvent:event];
    if(!self.dragging)
        [[self nextResponder] touchesEnded:touches withEvent:event];
}

- (void)dealloc {
    [super dealloc];
}


@end 

希望能帮到你

【讨论】:

  • 我有一个 UIScrollView 和一个名为 A 的自定义 UIView。自定义 UIView 称为 A 而不是 UIScrollView。这个UIScrollView 只是用来让我能够在 A 上放大/缩小。
  • 苹果不鼓励将事件直接发送给下一个响应者
【解决方案3】:

我尚未对此进行测试,但我相信您在视图 A(或其子视图)中处理触摸事件的方式将决定如何传递触摸事件。具体来说,如果您尝试使用以下方法:touchesBegantouchesMovestouchesEnded 等而不是 UIGestureRecognizer,您将不会以您想要的方式接收触摸。 Apple 设计了UIGestureRecognizer 来处理您所面临的问题。具体来说,UIScrollView 使用UIPanGestureRecognizer 来处理滚动。如果将UIPanGestureRecognizer 添加到View A 的每个子视图中,则在其中一个子视图上发生的任何“平移”都应发送到该子视图而不是UIScrollView。但是,如果您只是使用“原始”touches 方法,则UIScrollView 中的UIPanGestureRecognizer 将永远不会被取消。

一般来说,最好使用UIGestureRecognizer,而不是直接在视图中处理触摸。如果您需要以标准UIGestureRecognizer 无法提供的方式处理触摸,请继承UIGestureRecognizer 并在那里处理触摸。这样您就可以获得UIGestureRecognizer 的所有功能以及您自己的自定义触摸处理。我真的认为 Apple 打算让 UIGestureRecognizer 替换开发人员在 UIView 上使用的大部分(如果不是全部)自定义触摸处理代码。它允许代码重用,并且在减轻哪些代码处理哪些触摸事件时更容易处理。

【讨论】:

    【解决方案4】:

    注意:感谢大家的贡献,特别是 Aaron Hayman。

    我能够通过对我拥有的 UIScrollView 子类执行以下操作来弄清楚:

    -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
    {
       CGPoint pointOfContact = [gestureRecognizer locationInView:self];
    
        // The view with a tag of 200 is my A view.
        return (![[self hitTest:pointOfContact withEvent:nil] isEqual:[self viewWithTag:200]]);
    }
    

    【讨论】:

    • 太好了,我应该推荐子类化 UIScrollView。我要补充一点,您可能需要区分UIScrollView 的手势识别器。例如,您可能想要取消点击和平移,但不想取消捏合(缩放)。当locationInView 在您的一个子视图中返回一个点时,有时捏合不起作用可能会令人不安。您应该可以通过以下方式轻松完成此操作:if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]) return YES;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 2012-03-17
    • 2011-07-11
    • 2023-03-29
    • 1970-01-01
    相关资源
    最近更新 更多