Reputation: 9385
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.
i.e. 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!
Upvotes: 0
Views: 1849
Reputation: 62686
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.
Upvotes: 1
Reputation: 62686
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
Upvotes: 2