简体   繁体   English

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

[英]iOS: Gesture recogniser for smooth scrolling and flicking a View

I am building an iPad app where I needed to allow resizing views functionality using divider view provided between two views. 我正在构建一个iPad应用程序,我需要允许使用两个视图之间提供的分隔视图来调整视图功能。 The divider view is just a 20px height view between two half screen content views - please refer attached images. 分隔视图只是两个半屏内容视图之间的20px高度视图 - 请参阅附图。

When user scrolls this divider view up or down, both content views changes their sizes appropriately. 当用户向上或向下滚动此分隔视图时,两个内容视图都会相应地更改其大小。 I have extended UIView and implemented this using touchMoved delegate as code given below in touchesMoved delegate. 我已经扩展了UIView并使用touchMoved委托实现了这个代码,如下面touchesMoved委托中给出的代码。 It works fine. 它工作正常。 The only thing is missing with TouchMoved is you can't flick divider view to top or bottom directly. TouchMoved唯一缺少的是您无法直接将分割器视图轻弹到顶部或底部。 You have to drag all the way to top or bottom! 你必须一直拖到顶部或底部!

To support flicking the view I have tried UIPanGestureRecognizer but I don't see smooth dragging with it. 为了支持轻弹视图,我尝试了UIPanGestureRecognizer但我看不到它的平滑拖动。 Setting split-position of parent resizes both content views as shown in the code. 设置父级的拆分位置会调整两个内容视图的大小,如代码所示。 When I handle split position change in UIGestureRecognizerStateChanged state, just touching divider view flick it to top or bottom. 当我在UIGestureRecognizerStateChanged状态下处理分割位置变化时,只需触摸分割器视图就可以将其轻弹到顶部或底部。 Handling split position change in UIGestureRecognizerStateEnded does the same but I don't see content view resizing with dividerview scrolling! UIGestureRecognizerStateEnded中处理拆分位置更改会做同样的事情,但我看不到内容视图使用dividerview滚动调整大小!

Could someone please tell me how could I achieve both smooth scrolling of divider view with resizing content views (like touchMoved ) and flicking the view? 有人可以告诉我如何通过调整内容视图(如touchMoved )和轻弹视图来实现分隔视图的平滑滚动? Any alternative approach would also be fine. 任何替代方法也可以。 Thanks. 谢谢。

- (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;
    }
}

Initial screen 初始屏幕

初始屏幕

Increased top view size by scrolling divider view towards bottom. 通过向底部滚动分隔视图来增加顶视图大小。

通过滚动分隔视图增加顶视图大小

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 我想轻弹分隔视图,使其直接从任何位置移动到顶部

顶视图完全隐藏在这里,但我必须滚动分隔视图一直到顶部。我想轻弹分隔视图,使其直接从任何位置移动到顶部。

If I understand you correctly, you have two separate problems here. 如果我理解正确,你在这里有两个不同的问题。

1st: The 'unsmooth' dragging when using the GestureRecognizer. 1st:使用GestureRecognizer时“不平滑”的拖动。 The problem in your code is, that you add the translation every time the GR calls it's handle method. 代码中的问题是,每次GR调用它的句柄方法时都会添加转换。 Since the translation is measured continuously, you're adding a higher value every time it's called (ie the first call adds 10 to the split position, the 2nd 20, the 3rd 30 and so on). 由于平移是连续测量的,因此每次调用时都会增加一个更高的值(即第一个调用将10添加到分割位置,第二个调用增加20,第三个30等等)。

To solve this you should set the translation to zero after you've updated the split position: 要解决此问题,您应该在更新拆分位置后将转换设置为零:

- (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];
}

2nd: To allow the user to flick the split position to the top or bottom, you could check the velocity in UIGestureRecognizerStateEnded, and if it exeeds some value instantly set the splitposition to top or bottom. 第二步:要允许用户将分割位置轻弹到顶部或底部,您可以检查UIGestureRecognizerStateEnded中的速度,如果它执行某个值,立即将分割位置设置为顶部或底部。

But it might be more convenient to use a UISwipeGestureRecognizer. 但是使用UISwipeGestureRecognizer可能更方便。

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

In this case it might be necessary (not sure, maybe it's not) to require the SwipeGR to fail before the PanGR triggers by setting: 在这种情况下,可能有必要(不确定,可能不是)通过设置要求SwipeGR在PanGR触发之前失败:

[panGestureRecognizer requireGestureRecognizerToFail:swipeGestureRecognizer];

Hope that helped. 希望有所帮助。

Edit: Regarding your comment, I assume by frequency you mean velocity. 编辑:关于你的评论,我假设频率你的意思是速度。 If you only use the PanGR you could modify the code above to sth. 如果你只使用PanGR,你可以将上面的代码修改为...... like this: 像这样:

- (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];
}

I'm not sure if the velocity is signed, if not you've got to check for the translation again in the if-block. 我不确定速度是否已签名,如果不是,你必须在if-block中再次检查转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在iOS的imageview中添加手势识别器? - How to add a Gesture Recogniser in imageview in iOS? 是否建议在iOS应用中手动删除手势识别器 - Is it recommended to remove gesture recogniser manually in iOS apps 向UIWindow上添加的视图添加手势识别器 - Adding a gesture recogniser to a view which added on UIWindow 禁用和重新启用Page View Controller手势识别器? - Disable and Reenable Page View Controller gesture recogniser? View中的手势识别器和使用View Controller作为Target,我的设计错了吗? - Gesture recogniser in View and use View Controller as Target, is my design wrong? 将按钮视图添加到标签视图作为子视图时,手势识别器无法正常工作 - Gesture recogniser not working when added button view to the Label view as subview iOS Swipe Gesture Recogniser用于快节奏的游戏 - iOS Swipe Gesture Recogniser for a quick-paced game 在不使用手势识别器的情况下,通过轻按外部来缩小视图 - Shrink a view based on tapping outside, without using gesture recogniser 我可以将手势识别器的代码放在视图的子类中吗? - Can I put the code for a gesture recogniser in the subclass of a view? 适用于SceneKit IOS的​​平滑捏手势 - Smooth Pinch Gesture for SceneKit IOS
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM