Restrict the movement of subview inside superview

2020-02-13 06:15发布

I have a UIView which is my VC's view(self.view) inside which I have another UIView added as subview both looks like a square. I would like to limit the movement of subview inside the superview. Basically the subview should not go outside the superview bounds.
I did implement

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
// i check if point of touch is inside my superview i set the center i.e
UITouch *touch = [[UITouch allObjects] firstObject];
if (CGRectContainsPoint(subview.frame, [touch locationInView:self.view])) {
// set the center here... i.e
subview.center = [touch locationInView:self.view];
}

This works and subview is moving but it also moves outside the superview; how can I restrict the movement within the superview only?

I even tried something like .

if (CGRectContainsRect(self.view.bounds, subview.frame)) {
// this condition works but i don't know why my subview sticks to the sides of superview if i try to drag it through the bounds of superview
}

I don't do anything in touchesBegan, touchesCancelled, and nothing relevant in touchesEnd as well.

1条回答
对你真心纯属浪费
2楼-- · 2020-02-13 06:23

You need to check the "new frame" of the view you are moving, and compare its edges to the bounds of its superview:

@implementation DraggableView

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // restrict to superview bounds
    CGRect parentFrame = [self.superview bounds];

    UITouch *aTouch = [touches anyObject];
    CGPoint location = [aTouch locationInView:self];
    CGPoint previousLocation = [aTouch previousLocationInView:self];

    // new frame for this "draggable" subview, based on touch offset when moving
    CGRect newFrame = CGRectOffset(self.frame, (location.x - previousLocation.x), (location.y - previousLocation.y));

    if (newFrame.origin.x < 0) {

        // if the new left edge would be outside the superview (dragging left),
        // set the new origin.x to Zero
        newFrame.origin.x = 0;

    } else if (newFrame.origin.x + newFrame.size.width > parentFrame.size.width) {

        // if the right edge would be outside the superview (dragging right),
        // set the new origin.x to the width of the superview - the width of this view
        newFrame.origin.x = parentFrame.size.width - self.frame.size.width;

    }

    if (newFrame.origin.y < 0) {

        // if the new top edge would be outside the superview (dragging up),
        // set the new origin.y to Zero
        newFrame.origin.y = 0;

    } else if (newFrame.origin.y + newFrame.size.height > parentFrame.size.height) {

        // if the new bottom edge would be outside the superview (dragging down),
        // set the new origin.y to the height of the superview - the height of this view
        newFrame.origin.y = parentFrame.size.height - self.frame.size.height;

    }

    // update this view's frame
    self.frame = newFrame;
}

@end

This also uses the offset of the touch, instead of centering the view on the touch (so it doesn't "jump to your finger" when you start dragging).

Edit for clarification: In this image, the Blue view class is DraggableView... It cannot be dragged outside of its superView (the Red view).

enter image description here

查看更多
登录 后发表回答