Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting anchor point for UIView layer

I have a UIView subclass that I want to be able to move around within it's superview. When the user touches the UIView somewhere outside self.center but within self.bounds it "jumps" because I add the new location to self.center to achieve the actual move. To avoid this behavior I'm trying to set an anchor point that lets the user grab and drag the view anywhere within it's bounds.

My problem is that when I calculate the new anchor point (as shown in the code below) nothing happens, the view doesn't change position at all. On the other hand, if I set the anchor point to a precalculated point I can move the view (but then of course it "jumps" to the precalculated point). How come this doesn't work as expected?

Thanks.

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{
    // Only support single touches, anyObject retrieves only one touch
    UITouch *touch = [touches anyObject];
    CGPoint locationInView = [touch locationInView:self];

    // New location is somewhere within the superview
    CGPoint locationInSuperview = [touch locationInView:self.superview];

    // Set an anchorpoint that acts as starting point for the move
    // Doesn't work!
    self.layer.anchorPoint = CGPointMake(locationInView.x / self.bounds.size.width, locationInView.y / self.bounds.size.height);
    // Does work!
    self.layer.anchorPoint = CGPointMake(0.01, 0.0181818);

    // Move to new location
    self.center = locationInSuperview;
}
like image 680
Oskar Avatar asked Jan 27 '11 22:01

Oskar


1 Answers

As Kris Van Bael pointed out, your going to need to do the anchor point calculations in the touchsBegan:withEvent: method in order not to negate the movement. Additionally, since changing the layer's anchorPoint will move the view's initial position, you have to add an offset to the view's center point to avoid a 'jump' after the first touch.

You can do this by calculating (and adding to your view's center point) the offset based on the difference between the initial and final anchorPoints (multiplied by your view's width/height) or you could set the view's center to the initial touch point.

Something like this perhaps:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    CGPoint locationInView = [touch locationInView:self];
    CGPoint locationInSuperview = [touch locationInView:self.superview];

    self.layer.anchorPoint = CGPointMake(locationInView.x / self.frame.size.width, locationInView.y / self.frame.size.height);
    self.center = locationInSuperview;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    CGPoint locationInSuperview = [touch locationInView:self.superview];

    self.center = locationInSuperview;
}

More info on anchorPoint's from apple's docs here and a similar SO question I referenced here.

like image 166
Sam Avatar answered Sep 20 '22 08:09

Sam