简体   繁体   English

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

[英]Restrict a draggable UIView to bounds of SuperView

assume we have a UITableViewCell with an inner big custom UIImageView, like the image below: I have added UILongPressGestureRecOgnizer to the UITableViewCell, so after longPress user can move this big image. 假定我们有一个带有内部大自定义UIImageView的UITableViewCell,如下图所示:我已将UILongPressGestureRecOgnizer添加到UITableViewCell中,因此UILongPressGestureRecOgnizer用户可以移动此大图像。 but I want this movement be in the bound of UITableViewCell . 但我希望此运动在UITableViewCell 在此处输入图片说明

What I've done right now: 我现在所做的是:

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;

the problem is when I move my finger diagonally, the image movement is a little jerky. 问题是当我沿对角方向移动手指时,图像移动有点生涩。 while moving diagonally, for example when X is out of bound, if Y is valid, Y point should be updated. 在对角移动时(例如,当X越界时),如果Y有效,则应更新Y点。 what's wrong here? 怎么了 do you have any idea? 你有什么主意吗?

What I do for this is a little hard to follow, but here goes... 我为此所做的工作有些困难,但是这里...

I do the touch interaction inside the view that is moving. 我在移动的视图内进行触摸交互。 In touchesBegan touchesBegan

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

These are all class variables. 这些都是类变量。 Then in touchesMoved : 然后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;

All the fun stuff happens in the scrollLimit function: 所有有趣的事情都发生在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);

}

All of this makes sure that the view stays inside the bounds that you set (in my case just the superview bounds) and it also makes the dragging experience smooth and realistic. 所有这些确保了视图保持在您设置的边界之内(在我的情况下,仅是超级视图的边界),并且还使拖动体验变得流畅和真实。 Some other methods I have seen can cause your finger to get off of the item you are scrolling and never sync back up. 我见过的其他一些方法可能会使您的手指离开正在滚动的项目,并且从不同步备份。 I'm sure my code won't work for you as is, but it should get you in the right direction. 我确定我的代码无法按原样为您工作,但它可以为您提供正确的方向。

In my methods I also have simulated inertia for view "throwing" while still keeping the bounding superview box. 在我的方法中,我还模拟了视图“投掷”的惯性,同时仍然保留了边界超级视图框。 Since that is outside of your question and it took a very long time to get perfect, I'll leave that as an exercise to the reader... 由于这是您无法解决的问题,并且花了很长时间才能达到完美,因此我将其留给读者练习。

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

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