平移手势干扰滚动 [英] Pan gesture interferes with scroll

查看:121
本文介绍了平移手势干扰滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有三个视图控制器,它们是UIScrollView的一部分。我希望能够在三者之间滑动,尽管其中一个视图控制器有一个UIPanGestureRecognizer。我使用这个平移手势识别器允许用户上下拖动手指来增加和减少矩形UIView的高度。因此,这个UIPanGestureRecognizer只需要知道向上/向下平移,滚动视图可以使用水平平移。

I have three view controllers that are part of a UIScrollView. I want to be able to swipe between the three, although one of the view controllers has a UIPanGestureRecognizer. I use this pan gesture recognizer to allow the user to drag their finger up and down to increase and decrease the height of a rectangular UIView. Therefore, this UIPanGestureRecognizer only really needs to know about the upwards/downwards panning, and the scroll view can use the horizontal panning.

这方面的一个例子就像主屏幕;你可以向左或向右滑动,但也可以向下滑动以获得聚光灯。我想要这种机制。

An example of this, is like the home screen; you can swipe left or right, but also swipe down to get spotlight. I want this kind of mechanism.

这是我的代码:

- (void)pan:(UIPanGestureRecognizer *)aPan; // When pan guesture is recognised
{
CGPoint location = [aPan locationInView:self.view]; // Location of finger on screen
CGRect secondRect = CGRectMake(210.0, 45.0, 70.0, 325.0); // Rectangles of maximimum bar area
CGRect minuteRect = CGRectMake(125.0, 45.0, 70.0, 325.0);
CGRect hourRect = CGRectMake(41.0, 45.0, 70.0, 325.0);

if (CGRectContainsPoint(secondRect, location)) { // If finger is inside the 'second' rectangle

    CGPoint currentPoint = [aPan locationInView:self.view];

    currentPoint.y -= 80;  // Make sure animation doesn't go outside the bars' rectangle

    if (currentPoint.y < 0) {
    currentPoint.y = 0;
    }
    else if (currentPoint.y > 239) {
    currentPoint.y = 239;
    }

    currentPoint.y = 239.0 - currentPoint.y;

    CGFloat pointy = currentPoint.y - fmod(currentPoint.y, 4.0);

    [UIView animateWithDuration:0.01f  // Animate the bars to rise as the finger moves up and down
                     animations:^{
                         CGRect oldFrame = secondBar.frame;
                         secondBar.frame = CGRectMake(oldFrame.origin.x, (oldFrame.origin.y - (pointy - secondBar.frame.size.height)), oldFrame.size.width, (pointy));
                     }];

    CGFloat result = secondBar.frame.size.height - fmod(secondBar.frame.size.height, 4.0);

    secondInt = (result / 4.0); // Update labels with new time

    self->secondLabel.text = [NSString stringWithFormat:@"%02d", secondInt];
}

代码基本上是针对三个独立的矩形UIView重复的。

The code is basically repeated for three separate rectangular UIViews.

如果有人能告诉我如何将主屏风格的平移/滑动到我的应用程序中,那就太棒了!

If anyone can tell me how to get the homescreen-style panning/swiping into my app, that would be great!!

推荐答案

好的,这是简短的回答:

你必须使用 UIGestureRecognizer 的方法 -requireGestureRecognizerToFail:

这是一个很长的答案:

你必须做出平底锅如果 TimerViewController 的平移手势识别器失败,滚动视图的手势识别器将成功 。但是,如果初始移动是垂直的,那么该姿势( TimerViewController 的手势)应成功。如果它是水平的,它应该失败。
为了实现这一目标,我们必须继承 UIPanGestureRecognizer 并对其进行修改以满足这些需求。
以下是您需要做的事情:

You have to make the pan gesture recognizer of your scroll view to succeed only if the pan gesture recognizer of TimerViewController fails. However that gesture (TimerViewController's gesture) should only succeed if the initial movement is vertical. If it is horizontal it should fail. To accomplish this we have to subclass UIPanGestureRecognizer and modify it to fit those needs. Here is what you have to do:


  1. 忽略您之前回答所做的所有更改

  2. VerticalPanGestureRecognizer 添加到您的项目中。

  3. 修改 TimerViewController 如图所示。

  4. 修改 ScrollViewController ,如图所示。

  1. Disregard ALL the changes you made from my previous answer
  2. Add VerticalPanGestureRecognizer to your project.
  3. Modify TimerViewController as shown.
  4. Modify ScrollViewController as shown.

VerticalPanGestureRecognizer.h

#import <UIKit/UIKit.h>
#import <UIKit/UIGestureRecognizerSubclass.h>

@interface VerticalPanGestureRecognizer : UIPanGestureRecognizer

@end

VerticalPanGestureRecognizer.m

#import "VerticalPanGestureRecognizer.h"

@interface VerticalPanGestureRecognizer ()

@property (nonatomic, assign) CGPoint origLoc;

@end

@implementation VerticalPanGestureRecognizer

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

    self.origLoc = [[touches anyObject] locationInView:self.view.superview];
    [super touchesBegan:touches withEvent:event];
}

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

    if (self.state == UIGestureRecognizerStatePossible) {
        CGPoint loc = [[touches anyObject] locationInView:self.view.superview];
        CGFloat deltaX = fabs(loc.x - self.origLoc.x);
        CGFloat deltaY = fabs(loc.y - self.origLoc.y);
        if (deltaY < deltaX)
            self.state = UIGestureRecognizerStateFailed;
    }

    [super touchesMoved:touches withEvent:event];
}

@end

TimerViewController.h

// Your imports here

@interface TimerViewController : UIViewController

{
    // Your ivars here
}

// Add the following property
@property (nonatomic, strong) UIPanGestureRecognizer *pan;

// Your methods here

@end

TimerViewController.m

#import "TimerViewController.h"
#import "VerticalPanGestureRecognizer.h"

@implementation TimerViewController
@synthesize pan = _pan;

// prefersStatusBarHidden method here

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil // Initialise view controller
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self) {

        // Instantiate the pan gesture as "VerticalPanGestureRecognizer"
        self.pan = [[VerticalPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; // Create recogniser for a pan guesture
        self.pan.maximumNumberOfTouches = self.pan.minimumNumberOfTouches = 1;
        [self.view addGestureRecognizer:self.pan];
    }

    return self;
}

// The rest of your code here

@end

ScrollViewController.m

- (void)viewDidLoad
{
    // Your code here

    TimerViewController *tvc = [[TimerViewController alloc]init];
    CGRect frame = tvc.view.frame;
    frame.origin.x = 320;
    tvc.view.frame = frame;

    // Add the following line 
    [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:tvc.pan];

    [self addChildViewController:tvc];
    [self.scrollView addSubview:tvc.view];
    [tvc didMoveToParentViewController:self];

    // More code here
}

这种新方法工作得很好。我测试了它。
如果您有更多问题,请告诉我。

This new approach works perfectly. I tested it. Let me know if you have more questions.

干杯!

UPDATE

要回答您在评论中发布的问题,请执行以下操作:

To answer the question you posted on the comments, here is what you have to do:

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

    BarsViewController *bvc = [[BarsViewController alloc]init];
    [self addChildViewController:bvc];
    [self.scrollView addSubview:bvc.view];
    [bvc didMoveToParentViewController:self];

    TimerViewController *tvc = [[TimerViewController alloc]init];
    CGRect frame = tvc.view.frame;
    frame.origin.x = 320;
    tvc.view.frame = frame;

    [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:tvc.pan];
    [self addChildViewController:tvc];
    [self.scrollView addSubview:tvc.view];
    [tvc didMoveToParentViewController:self];

    StopwatchViewController *svc = [[StopwatchViewController alloc] init];
    frame = svc.view.frame;
    frame.origin.x = 320*2;
    svc.view.frame = frame;

    [self addChildViewController:svc];
    [self.scrollView addSubview:svc.view];
    [svc didMoveToParentViewController:self];

    self.scrollView.contentSize = CGSizeMake(320*3, self.view.frame.size.height);
    self.scrollView.pagingEnabled = YES;

    [self.scrollView setShowsHorizontalScrollIndicator:NO];
}

再次,我测试了它并且它正在工作。您只需为条形图添加手势识别器

Again, I tested it and it's working. You just have to add the gesture recognizer for the bars

这篇关于平移手势干扰滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆