简体   繁体   English

如何通过Pan手势限制可移动视图

[英]How to restrict a moveable view by Pan gesture

I have a UIImageView which is moveable via a pan gesture. 我有一个可通过平移手势移动的UIImageView

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

I would like to restrict the area this can be moved on screen. 我想限制可以在屏幕上移动的区域。 Rather than the user be able to drag the view right to the side of the screen, I want to restrict it by a margin of some sort. 而不是用户能够将视图直接拖动到屏幕的一侧,我想限制它的某种边距。 How can I do this? 我怎样才能做到这一点?

Also, how is this then handled when rotated? 另外,旋转后如何处理?

EDIT --- 编辑---

#pragma mark - Gesture Recognizer
-(void)handlePan:(UIPanGestureRecognizer *)gesture {
    NSLog(@"Pan Gesture");
    gesture.view.center = [gesture locationInView:self.view];
}

This is my current method to handle the pan. 这是我目前处理平底锅的方法。 What I need to do is continue to move the imageview by the center point and also restrict its movement when close to the edge of the screen by 50 for example. 我需要做的是继续按中心点移动图像视图,并在靠近屏幕边缘时将其移动限制为50。

One possible solution to this is in your handlePan method, check the location of the point on the screen, and only commit the change if it is within the bounds you wish to restrict it to. 一种可能的解决方案是在handlePan方法中,检查屏幕上点的位置,并且只有在您希望将其限制为的范围内时才提交更改。

For ex. 对于前者

-(void) handlePan:(UIGestureRecognizer*)panGes{

    CGPoint point = [panGes locationInView:self.view];

    //Only allow movement up to within 100 pixels of the right bound of the screen
    if (point.x < [UIScreen mainScreen].bounds.size.width - 100) {

        CGRect newframe = CGRectMake(point.x, point.y, theImageView.frame.size.width, theImageView.frame.size.height);

        theImageView.frame = newframe;

    }

}

I believe this would also correctly handle any screen rotation 我相信这也可以正确处理任何屏幕旋转

EDIT 编辑

To move your image view by the center of its frame, the handlePan method could look something like this. 要通过框架的中心移动图像视图, handlePan方法可能看起来像这样。

-(void)handlePan:(UIPanGestureRecognizer *)gesture {

    CGPoint point = [gesture locationInView:self.view];

    //Only allow movement up to within 50 pixels of the bounds of the screen
    //Ex. (IPhone 5)
    CGRect boundsRect = CGRectMake(50, 50, 220, 448);

    if (CGRectContainsPoint(boundsRect, point)) {
        imgView.center = point;
    }       
}

Check whether the point is within your desired bounds, and if so, set the center of your image view frame to that point. 检查点是否在您想要的范围内,如果是,请将图像视图框的中心设置为该点。

I'm not sure if I'm being over-simplistic here but I think you can accomplish this by using an if clause. 我不确定我是否过于简单化,但我认为你可以通过使用if子句来实现这一点。

-(void)handlePan:(UIPanGestureRecognizer*)gesture {

    UIImageView *viewToDrag = gesture.view; // this is the view you want to move

    CGPoint translation = [gesture translationInView:viewToDrag.superview]; // get the movement delta

    CGRect movedFrame = CGRectOffset(viewToDrag.frame, translation.x, translation.y); // this is the new (moved) frame

    // Now this is the critical part because I don't know if your "margin"
    // is a CGRect or maybe some int values, the important thing here is
    // to compare if the "movedFrame" values are in the allowed movement area

    // Assuming that your margin is a CGRect you could do the following:
    if (CGRectContainsRect(yourPermissibleMargin, movedFrame)) {
        CGPoint newCenter = CGPointMake(CGRectGetMidX(movedFrame), CGRectGetMidY(movedFrame));
        viewToDrag.center = newCenter; // Move your view
    }

    // -OR-

    // If you have your margins as int values you could do the following:
    if ( (movedFrame.origin.x + movedFrame.size.width) < 50) {
        CGPoint newCenter = CGPointMake(CGRectGetMidX(movedFrame), CGRectGetMidY(movedFrame));
        viewToDrag.center = newCenter; // Move your view
    }
}

You'll probably have to adapt this to meet your specific needs. 您可能需要调整它以满足您的特定需求。

Hope this helps! 希望这可以帮助!

Here is the answer in Swift 4 - Restrict the view's movement to superview 以下是Swift 4中的答案 - 将视图的移动限制为superview

@objc func handlePan(_ gestureRecognizer: UIPanGestureRecognizer)
{
    // Allows smooth movement of stickers.
    if gestureRecognizer.state == .began || gestureRecognizer.state == .changed
    {
        let point = gestureRecognizer.location(in: self.superview)
        if let superview = self.superview
        {
            let restrictByPoint : CGFloat = 30.0
            let superBounds = CGRect(x: superview.bounds.origin.x + restrictByPoint, y: superview.bounds.origin.y + restrictByPoint, width: superview.bounds.size.width - 2*restrictByPoint, height: superview.bounds.size.height - 2*restrictByPoint)
            if (superBounds.contains(point))
            {
                let translation = gestureRecognizer.translation(in: self.superview)
                gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x + translation.x, y: gestureRecognizer.view!.center.y + translation.y)
                gestureRecognizer.setTranslation(CGPoint.zero, in: self.superview)
            }
        }
    }
}

If you want more control over it, match restrictByPoint value to your movable view's frame. 如果要对其进行更多控制,请将restrictByPoint值与可移动视图的帧匹配。

- (void)dragAction:(UIPanGestureRecognizer *)gesture{
     UILabel *label = (UILabel *)gesture.view;
     CGPoint translation = [gesture translationInView:label];
     if (CGRectContainsPoint(label.frame, [gesture locationInView:label] )) {
         label.center = CGPointMake(label.center.x,
                                label.center.y);
        [gesture setTranslation:CGPointZero inView:label];
   }
   else{
       label.center = CGPointMake(label.center.x,
                                label.center.y + translation.y);
        [gesture setTranslation:CGPointZero inView:label];
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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