iOS:用于平滑滚动和轻弹视图的手势识别器

时间:2012-10-12 08:22:58

标签: ios ipad uiview uigesturerecognizer

我正在构建一个iPad应用程序,我需要允许使用两个视图之间提供的分隔视图来调整视图功能。分隔视图只是两个半屏内容视图之间的20px高度视图 - 请参阅附图。

当用户向上或向下滚动此分隔视图时,两个内容视图都会相应地更改其大小。我已将UIView扩展为touchMoved并使用touchesMoved委托作为下面TouchMoved委托中给出的代码实现此目的。它工作正常。 UIPanGestureRecognizer唯一缺少的是您无法直接将分隔视图轻弹到顶部或底部。你必须一直拖到顶部或底部!

要支持点击我尝试UIGestureRecognizerStateChanged的视图,但我看不到它的平滑拖动。设置父级的拆分位置会调整两个内容视图的大小,如代码所示。当我在UIGestureRecognizerStateEnded状态下处理分割位置变化时,只需触摸分割器视图即可将其轻弹到顶部或底部。在touchMoved中处理拆分位置更改会做同样的事情,但我看不到使用dividerview滚动调整内容视图的大小!

有人可以告诉我如何通过调整内容视图(如- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; if (touch) { CGPoint lastPt = [touch previousLocationInView:self]; CGPoint pt = [touch locationInView:self]; float offset = pt.y - lastPt.y; self.parentViewController.splitPosition = self.parentViewController.splitPosition + offset; } } - (void)handlePan:(UIPanGestureRecognizer*)recognizer { CGPoint translation = [recognizer translationInView:recognizer.view]; CGPoint velocity = [recognizer velocityInView:recognizer.view]; if (recognizer.state == UIGestureRecognizerStateBegan) { } else if (recognizer.state == UIGestureRecognizerStateChanged) { // If I change split position here, I don't see smooth scrolling dividerview...it directly jumps to the top or bottom! self.parentViewController.splitPosition = self.parentViewController.splitPosition + translation.y; } else if (recognizer.state == UIGestureRecognizerStateEnded) { // If I change split position here, the same thing happens at end and I don't see my divider view moving with my scrolling and resizing my views. self.parentViewController.splitPosition = self.parentViewController.splitPosition + translation.y; } } )并轻弹视图来实现分区视图的平滑滚动?任何替代方法也可以。感谢。

{{1}}
  

初始屏幕

Initial screen

  

通过向底部滚动分隔视图来增加顶视图大小。

Increased top view size by scrolling divider view

  

顶视图完全隐藏在这里,但我必须滚动分隔视图全部   通往顶部的道路。我想直接点击分隔线视图   从任何位置到顶部

Top view is totally hidden here but I have to scroll divider view all the way to top. I want to flick the divider view so that it directly goes from any position to top.

1 个答案:

答案 0 :(得分:7)

如果我理解正确,你在这里有两个不同的问题。

1st:使用GestureRecognizer时“不平滑”的拖动。代码中的问题是,每次GR调用它的句柄方法时都会添加转换。由于翻译是连续测量的,因此每次调用时都会增加一个更高的值(即第一个调用将10添加到分割位置,第二个调用增加20,第三个30等等。)

要解决此问题,您应该在更新拆分位置后将转换设置为零:

- (void)handlePan:(UIPanGestureRecognizer*)recognizer {

    CGPoint translation = [recognizer translationInView:recognizer.view];

    if (recognizer.state == UIGestureRecognizerStateChanged) {
       self.parentViewController.splitPosition = self.parentViewController.splitPosition + translation.y;
    } 
    [recognizer setTranslation:CGPointZero inView:recognizer.view];
}

第二:要允许用户将分割位置轻弹到顶部或底部,您可以检查UIGestureRecognizerStateEnded中的速度,如果它执行某个值,立即将分割位置设置为顶部或底部。

但是使用UISwipeGestureRecognizer可能更方便。

- (void)handleSwipe:(UISwipeGestureRecognizer *)gr
{
    if (gr.direction == UISwipeGestureRecognizerDirectionUp){
        [self.parentViewController moveSplitViewToTop];
    }
    else if (gr.direction == UISwipeGestureRecognizerDirectionDown){
        [self.parentViewController moveSplitViewToBottom];
    }
}

在这种情况下,可能有必要(不确定,可能不是)通过设置要求SwipeGR在PanGR触发之前失败:

[panGestureRecognizer requireGestureRecognizerToFail:swipeGestureRecognizer];

希望有所帮助。

编辑: 关于你的评论,我假设你的意思是速度。如果你只使用PanGR,你可以将上面的代码修改为......像这样:

- (void)handlePan:(UIPanGestureRecognizer*)recognizer {

    CGPoint translation = [recognizer translationInView:recognizer.view];
    CGPoint velocity = [recognizer velocityInView:recognizer.view];

    if (recognizer.state == UIGestureRecognizerStateChanged) {
       self.parentViewController.splitPosition = self.parentViewController.splitPosition + translation.y;
    } 
    else if (recognizer.state == UIGestureRecognizerStateEnded){
        if (velocity.y > someValue){
            [self.parentViewController moveSplitViewToBottom];
        }
        else if (velocity.y < someValue){
            [self.parentViewController moveSplitViewToTop];
        }
    }
    [recognizer setTranslation:CGPointZero inView:recognizer.view];
}

我不确定速度是否已签名,如果不是,你必须在if-block中再次检查翻译。