将可拖动的UIView限制为SuperView的边界

时间:2016-05-27 19:37:07

标签: ios objective-c uigesturerecognizer

假设我们有一个带有内部大自定义UIImageView的UITableViewCell,如下图所示: 我已将UILongPressGestureRecOgnizer添加到UITableViewCell,因此在longPress用户可以移动这个大图像。但是我希望这个运动在UITableViewCell的范围内。 enter image description here

我现在所做的:

UIView *view = sender.view;
CGPoint point = [sender locationInView:view.superview];
if (sender.state == UIGestureRecognizerStateChanged)
{
    CGPoint oldCenter = view.center;
    CGPoint newCenter = oldCenter;
    CGFloat deltaX = point.x - _priorPoint.x;
    CGFloat deltaY = point.y - _priorPoint.y;
    newCenter.x += deltaX;
    newCenter.y += deltaY;
    CGRect oldFrame = view.frame;
    CGRect newFrame = CGRectMake(oldFrame.origin.x + deltaX, oldFrame.origin.y+deltaY, view.width, view.height);

    if (CGRectContainsRect(newFrame, self.bounds)) {
        self.customImageView.center = newCenter;
    }
    else
    {
        CGFloat newX = newFrame.origin.x;
        CGFloat newY = newFrame.origin.y;
        if (newX<view.x) {
            newX = oldFrame.origin.x;
        }
        else if ((newFrame.origin.x + newFrame.size.width)>view.right)
        {
            newX = oldFrame.origin.x;
        }

        if (newY<view.y) {
            newY = oldFrame.origin.y;
        }
        else if ((newY + newFrame.size.height)>view.bottom)
        {
            newY = view.y;
        }
        NSLog(@"newX:%f, newY:%f", newX, newY);
        newFrame = CGRectMake(newX, newY, view.width, view.height);
        self.customImageView.frame = newFrame;
    }
_priorPoint = point;
问题是,当我沿对角线移动手指时,图像移动有点不稳定。在对角移动时,例如当X超出范围时,如果Y有效,则应更新Y点。 这里有什么不对?你有什么主意吗?

1 个答案:

答案 0 :(得分:2)

我为此做的事情有点难以理解,但这里有......

我在正在移动的视图中进行触摸交互。在touchesBegan

drawingFrame = self.frame;
initialViewOrigin = self.frame.origin;
startingTouch = [[touches anyObject] locationInView:[self superview]];

这些都是类变量。然后在touchesMoved

lastTouchPoint = [[touches anyObject] locationInView:[self superview]];
float newLocationX = initialViewOrigin.x + (p.x - startingTouch.x);
float newLocationY = initialViewOrigin.y + (p.y - startingTouch.y);

//Do some location checks for sending it too far off the screen or whatnot

drawingFrame.origin = [self scrollLimit:newLocationX y:newLocationY];

CGRect frame = self.frame;
frame.origin.x = drawingFrame.origin.x;
frame.origin.y = drawingFrame.origin.y;
self.frame = frame;

所有有趣的事情都发生在scrollLimit函数中:

-(CGPoint)scrollLimit:(float)x1 y:(float)y1
{
    //My app always requires landscape, so make sure the parent's sizes are taken accordingly
    int parentHeight = MIN(self.superview.frame.size.width,self.superview.frame.size.height);
    int parentWidth = MAX(self.superview.frame.size.width,self.superview.frame.size.height);

    if(self.frame.size.width < parentWidth)
    {
        if(x1 < 1)
        {
            x1 = 1;
        }
        else if(x1 >= parentWidth - self.frame.size.width)
        {
            x1 = parentWidth - self.frame.size.width;
        }
    }
    else{
        x1 = initialViewOrigin.x;
    }


    if(self.frame.size.height < parentHeight)
    {
        if(y1 < 1)
        {
            y1 = 1;
        }
        else if(y1 > parentHeight - self.frame.size.height)
        {
            y1 = parentHeight - self.frame.size.height;
        }
    }
    else{
        y1 = initialViewOrigin.y;
    }

    return CGPointMake(x1,y1);

}

所有这些都确保视图保持在您设置的边界内(在我的情况下只是超视图边界),它还使拖动体验流畅而逼真。我见过的其他一些方法可能会导致您的手指离开您正在滚动的项目并且从不同步备份。我确信我的代码不会按原样为你工作,但它应该让你朝着正确的方向前进。

在我的方法中,我也有模拟惯性观察&#34;投掷&#34;同时仍然保持边界超视图框。既然这不在你的问题之内,而且需要很长时间才能完美,我会将其作为练习留给读者...