平移手势干扰滚动

时间:2013-11-14 18:38:51

标签: ios objective-c uiscrollview swipe uipangesturerecognizer

我有三个视图控制器,它们是UIScrollView的一部分。我希望能够在三者之间滑动,尽管其中一个视图控制器有一个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重复的。

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

1 个答案:

答案 0 :(得分:6)

好的,这是简短的回答:

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

这是一个很长的答案:

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

  1. 忽略您之前回答中所做的所有更改
  2. VerticalPanGestureRecognizer添加到您的项目中。
  3. 如图所示修改TimerViewController
  4. 如图所示修改ScrollViewController
  5. <强> 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
    }
    

    这种新方法非常有效。我测试了它。 如果您有更多问题,请与我们联系。

    干杯!

    <强>更新

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

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

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