简体   繁体   中英

Stop UIPanGestureRecognizer from moving UIView vertically when inside a UIScrollView

I would like to have a pan gesture that only moves the UIView horizontally.

So far, at the start of the pan gesture, only horizontal movements are allowed, but once the pan gesture has started, the UIView moves both horizontally and vertically .

  • How do I stop the UIView from moving vertically at all times ?
  • Is there any way that the top of the UIView can always be at the top of the screen ?

ie it never moves vertically from its set position

Here is my current code:

- (void)panePanned:(UIPanGestureRecognizer *)gestureRecognizer
{    
    switch (gestureRecognizer.state) {
        case UIGestureRecognizerStateBegan: {
            self.paneStartLocation = [gestureRecognizer locationInView:self.mainView];
            self.paneVelocity = 0.0;
            break;
        }
        case UIGestureRecognizerStateChanged: {
            CGPoint panLocationInPaneView = [gestureRecognizer locationInView:self.mainView];
            CGFloat velocity = -(self.paneStartLocation.x - panLocationInPaneView.x);
            CGRect newFrame = self.mainView.frame;

            newFrame.origin.x += (panLocationInPaneView.x - self.paneStartLocation.x);
            if (newFrame.origin.x < 0.0) newFrame.origin.x = 0.0;
            self.mainView.frame = newFrame;

            if (velocity != 0) {
                self.paneVelocity = velocity;
            }
            break;
        }
        case UIGestureRecognizerStateEnded: {
            [self animate];
            break;
        }
        default:
            break;
    }
}

Thanks!

Try disabling scrolling on state begun and re-enabling it on state ended.

[scrollView setScrollEnabled:NO];    // in case UIGestureRecognizerStateBegan
[scrollView setScrollEnabled:YES];   // in case UIGestureRecognizerStateEnded

I did learn a couple things by building this myself. I think the pan logic can be simplified, and I think it can be made to work without disabling scrolling.

Try this: create a new single-view application project. Add a scroll view in storyboard. Add an outlet called 'scrollView' connecting to the ViewController. In ViewController.m add this code:

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;  // connected in storyboard
@end

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

    for (int i=0; i<60; i++) {
        UIView *draggableView = [[UIView alloc] initWithFrame:CGRectMake(10, i*40, 34, 34)];
        draggableView.backgroundColor = [UIColor redColor];

        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
        [draggableView addGestureRecognizer:pan];

        [self.scrollView addSubview:draggableView];
    }
    self.scrollView.contentSize = CGSizeMake(320, 60*40);
}

This adds a bunch of draggable views to the scroll view, giving each a pan gesture recognizer. I made a pan method like yours, except much simpler...

- (void)pan:(UIPanGestureRecognizer *)gr {

    switch (gr.state) {
        case UIGestureRecognizerStateBegan: {
            break;
        }
        case UIGestureRecognizerStateChanged: {
            UIView *view = gr.view;
            CGRect frame = view.frame;

            gr.view.frame = CGRectMake([gr translationInView:view].x, frame.origin.y, frame.size.width, frame.size.height);
            break;
        }
        case UIGestureRecognizerStateEnded: {
            break;
        }
        default:
            break;
    }
}

That's it. I don't disable scrolling, but we get the behavior that I think you're looking for. Glad your solution is working, but try out a project like this and see if it tells you anything about what you're up to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM