【问题标题】:iOS: Can I override pinch in/out behavior of UIScrollView?iOS:我可以覆盖 UIScrollView 的收缩/收缩行为吗?
【发布时间】:2011-09-26 05:14:23
【问题描述】:

我正在UIView 上绘制图表,UIScrollView 包含该图表,以便用户可以水平滚动查看整个图表。

现在我想在用户用两根手指捏合时缩放图形,但我不想在 X 和 Y 方向上以相同的速率缩放视图,而是想通过更改 X 比例仅在 X 方向上缩放, 不改变 Y 比例。

我想我必须抓住捏合/张开手势并重新绘制图形,覆盖默认的缩放行为。

但是有没有办法做到这一点?

我一直很难捕捉到UIScrollView 上的捏合手势,因为它在开始滚动时会取消触摸。即使在UIScrollView 取消触摸后,我也希望缩放工作。 :(

谢谢, 库拉

【问题讨论】:

    标签: iphone ios uiscrollview


    【解决方案1】:

    您应该能够继承 UIScrollView 并覆盖 touchesBegan: 方法。不要调用 [super touchesBegan:] 而是根据需要调整缩放:

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        //Anything you want. Probably you would want to store all the touches
        //or their values, so that you can compare them to the touches
        //in the touchesEnded: method, 
        //thus letting you know what the pinch amount was
    }
    

    如果你喜欢,可以判断是不是捏,如果不是,调用super方法,自定义捏只自己处理。

    【讨论】:

    • 这可能不再起作用,因为UIScrollView 现在使用多个手势识别器,并且在这些和touch 方法之间的交互中,这些方法通常会丢失 - - - 当尝试从滚动视图中实现“拖动”,我必须使用手势识别器来实现
    • 我猜这是有道理的。虽然如果你仍然想这样做,你应该能够只继承 UIView 并获取它的触摸事件,然后使用这些来操作你放在 UIView 之上的 UIScrollView?
    • 马特,谢谢您的回复。我已经尝试过了,但是一旦滚动开始,触摸就会被 UIScrollView 取消,之后就无法再处理它们了。如果我将 UIScrollView 子类化,或者将 UIView 子类化并将其放在 UIScrollView 上,也是一样的。
    【解决方案2】:

    您应该访问gestureRecognizers(在 UIView 中定义),其中有几个被滚动视图使用,

    找出哪一个是捏合识别器并在滚动视图上调用removeGestureRecognizer:,然后创建您自己的并让它完成工作,用addGestureRecognizer: 添加回来。

    这些都是公共 API, 识别器以及它们的顺序不是(当前), 所以在访问它们时要防御性地编程

    (这是操作 UIKit 视图的一种完全有效的方法,Apple 不会/不应该对此有任何问题 - 尽管他们不保证它在未来的任何版本中都能正常工作)

    【讨论】:

    • +1 我正在用代码示例解决这个问题,但这是需要做的,手势识别器在触摸事件之前触发,通常不会发送 touchesBegan 和类似事件。遍历gestureRecognizers并寻找任何isKindOfClass:[UIPinchGestureRecognizer class]
    • bshirley & Joe,感谢您的回复。我可以在 UIScrollView 实例上找到 3 个手势识别器,其中之一是 UIScrollViewPinchGestureRecognizer。我试图删除它并添加了我的自定义手势识别器,但它崩溃了,因为 UIScrollView 总是尝试专门向 UIScrollViewPinchGestureRecognizer 对象发送消息,该对象已被删除并释放。想到了一个想法,调用[UIGestureRecognizer removeTarget:action:]来移除默认的pinch action,并添加一个新的,但是action好像是[UIScrollView handleGesture:],没有文档记录。 :(
    • 添加您的识别器,暂停该识别器,然后告诉该识别器它需要您失败才能成功
    • 谢谢 bshirley。我会试试的。 ;)
    【解决方案3】:

    虽然不能删除现有的捏合手势识别器,但可以禁用它,然后添加自己的:

    // Disable existing recognizer
    for (UIGestureRecognizer* recognizer in [_scrollView gestureRecognizers]) {
        if ([recognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
            [recognizer setEnabled:NO];
        }
    }
    
    // Add our own
    UIPinchGestureRecognizer* pinchRecognizer = 
      [[UIPinchGestureRecognizer alloc] initWithTarget:self 
                                                action:@selector(pinch:)];
    [_scrollView addGestureRecognizer:pinchRecognizer];
    [pinchRecognizer release];
    

    然后在

    - (void) pinch:(UIPinchGestureRecognizer*)recognizer { .. }
    

    使用

    [recognizer locationOfTouch:0 inView:..]
    [recognizer locationOfTouch:1 inView:..]
    

    判断用户是水平捏还是竖捏。

    【讨论】:

    • 这是一个简单的解决方案。 :) 谢谢edsko!
    • 即使不禁用退出手势,您也可以添加新手势。
    • 来自遥远未来的快速评论:iOS 5,在这个答案写完三个月后发布,添加了-[UIScrollView pinchGestureRecognizer],所以你不必做那个线性搜索,希望苹果没有'不要做任何太不正统的事情。
    【解决方案4】:

    Edsko 和 bshirley 的答案很好,但他们不知道在哪里放置代码。

    首先,我把它放在viewDidLoad方法中,但是在滚动视图中没有找到捏手势识别器(可能是因为我的滚动视图是一个IBOutlet)。

    然后我尝试了viewWillAppearviewDidAppearUIPinchGestureRecognizer 就在这里。

    【讨论】:

    • 是的。你说得对。还有viewDidLayoutSubviews
    猜你喜欢
    • 2015-11-06
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多