平移手势会干扰滚动

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

一个例子就是主屏幕。 您可以向左或向右滑动,也可以向下滑动以获得聚光灯。 我想要这种机制。

这是我的泛代码:

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

代码基本上重复三个单独的矩形UIViews。

如果有人能告诉我如何让主屏幕式的平移/滑动到我的应用程序,这将是伟大的!

好的,下面是简短的回答:

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

这是一个长的答案:

只有TimerViewController的平移手势识别TimerViewController失败时,才能使滚动视图的平移手势识别器成功。 然而,这个手势( TimerViewController的手势) 只有初始移动是垂直的时候才能成功。 如果它是水平的,它应该失败。 为了达到这个目的,我们必须UIPanGestureRecognizer并修改它以适应这些需求。 这是你必须做的:

  1. 无视你从我以前的答案所做的所有更改
  2. VerticalPanGestureRecognizer添加到您的项目。
  3. 如图所示修改TimerViewController
  4. 如图所示修改ScrollViewController

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 } 

这种新方法完美运作。 我testing了它。 让我知道你是否有更多的问题。

干杯!

UPDATE

要回答你在评论中发布的问题,你需要做的是:

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

再次,我testing了它,它正在工作。 你只需要添加手势识别器的酒吧