UIScrollView向子视图发送触摸

时间:2012-08-14 07:38:43

标签: iphone ios ipad uiview uiscrollview

注意:我已经阅读了一些关于UIScrollView发送触摸到子视图(this所包含的内容的问题,虽然我已经投了票,但它还没有工作正如我打算的那样)。

我拥有的内容:我有一个UIScrollView,其中包含自定义UIView(让我们称之为 A )整个UIScrollView。我也可以将其他自定义UIViews放入 A

关于我正在执行此操作的代码:

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

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

  

现在,行为的变化取决于"时间长度"的   首先触摸UIView。如果它很短,那么相对拖动   管理,因为它是UIScrollView的滚动。如果它很长,那么   我在UIView中获取了touchesMoved:事件。

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


修改1.0

我在通用frame中拥有此 A 视图的唯一原因是因为我希望能够放大/缩小 A 查看。所以我正在做以下事情:

UIScrollView

一开始我没有- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { return customView; // this is the A view } 内的 A 视图,我唯一做的就是将 A 添加为子视图我的UIScrollView根视图,一切顺利。 如果还有其他方法可以启用放大/缩小功能,我很乐意接受答案。

4 个答案:

答案 0 :(得分:8)

注意:感谢大家的贡献,特别是对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]]);
}

答案 1 :(得分:4)

我没有对此进行过测试,但我相信您在View A(或其子视图)中处理触摸事件的方式将决定触摸事件的传递方式。具体来说,如果您尝试使用这些方法:touchesBegantouchesMovestouchesEnded等,而不是UIGestureRecognizer,那么您将无法接触到的方式想。 Apple设计UIGestureRecognizer来处理你所面临的问题。具体来说,UIScrollView使用UIPanGestureRecognizer来处理滚动。如果您为UIPanGestureRecognizer的每个子视图添加View A,则应将其中一个子视图发送到该子视图而不是UIScrollView。但是,如果您只是使用“原始”touches方法,UIPanGestureRecognizer中的UIScrollView将永远不会被取消。

通常,最好使用UIGestureRecognizer而不是直接在视图中处理触摸。如果您需要以没有标准UIGestureRecognizer可以提供的方式处理的触摸,则继承UIGestureRecognizer并处理那里的触摸。这样,您就可以获得UIGestureRecognizer的所有功能以及您自己的自定义触摸处理功能。我真的认为Apple希望UIGestureRecognizer替换大多数(如果不是全部)开发人员在UIView上使用的自定义触摸处理代码。它允许代码重用,并且在减轻代码处理触摸事件时处理起来要容易得多。

答案 2 :(得分:0)

Jacky,我需要类似的东西:在建筑计划(你的A,在我的例子中是UIScrollView的子类)中,让用户放置并调整对象大小(称之为Bs)。以下是我采取这种行为的原因草图:

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

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

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

  • 在嵌入式B中,停止超级视图A取消点击,因此它不会干扰在B上开始的手势。

    touchesBegan:方法中,向上搜索视图层次结构(使用视图的superview属性),直到找到UIScrollView,并将其canCancelContentTouches设置为{{ 1}}。请记住您更改的超级视图,并使用B的NOtouchesEnded方法恢复此属性。

我对这是否也适合您感兴趣。祝你好运!

比康夫

答案 3 :(得分:0)

我认为你最好用“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 

希望能帮到你