Animate the height of UILabel to 0 - ios

I've got a UILabel and what I want to do is to smoothly change it's height to 0.
CGRect newFrame = self.label1.frame;
newFrame.size.height = 0;
[UIView animateWithDuration:1.0 animations:^{
self.label1.frame = newFrame;
}];
The problem is that the animation is jamming does some wierd things. I guess that the label is trying to resize and reposition it's text and that is why it does not work. I've tried like every possible combination of properties on the label but without success.

You could enclose your UILabel into another UIView, set the enclosing UIView autoresizesSubviews' property to NO and clipToBounds to YES, and then animate the height of the enclosing UIView...

Try with a transform. I dug this code out for you:
//[self setAnchorPoint:CGPointMake(0.5, 1.0) forView:self.label];
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationCurveEaseInOut
animations:^{
//Scale the height to close to zero
//0.00001, because 0.0 behaves strange
self.label.transform = CGAffineTransformMakeScale(1, 0.00001);
}
completion:^(BOOL finished) {
self.label.hidden = YES;
}];
This will shrink it into the middle. If you want it to shrink to the top or bottom, you will need to set an anchor point. I also have some code for this too:
- (void) setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view {
CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x, view.bounds.size.height * anchorPoint.y);
CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x, view.bounds.size.height * view.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
CGPoint position = view.layer.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
view.layer.position = position;
view.layer.anchorPoint = anchorPoint;
}

Related

Scale animation in background from another anchorPoint

Ive done a Scaling animation for background image with an arrow in it,well by scaling the image(it includes the arrow) meaning its a whole background. it scales from the center of the background. but i want to start scaling from the center of arrow.
i want to achieve this :
Then to become with scale:
What i have to change in my code:
self.blueBackground.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
[UIView animateWithDuration:5 animations:^{
self.blueBackground.transform = CGAffineTransformScale(CGAffineTransformIdentity, 30, 30);
} completion:^(BOOL finished) {
}];
With my current code the scale start from center of background so the arrow end up at the right (out the bounds of screen).
Try something like this:
- (void)animateArrow
{
self.blueBackground.transform = CGAffineTransformIdentity;
[UIView animateWithDuration:5 animations:^{
ScaleViewAboutPointInBounds(self.blueBackground, arrowCenter, 30);
} completion:^(BOOL finished) {
}];
}
static void ScaleViewAboutPointInBounds(UIView *view, CGPoint point, CGFloat scaleAmount)
{
CGFloat xAnchor = view.layer.anchorPoint.x * CGRectGetWidth(view.bounds);
CGFloat yAnchor = view.layer.anchorPoint.y * CGRectGetHeight(view.bounds);
CGFloat xOffset = point.x - xAnchor;
CGFloat yOffset = point.y - yAnchor;
CGAffineTransform shift = CGAffineTransformMakeTranslation(-xOffset, -yOffset);
CGAffineTransform unshift = CGAffineTransformMakeTranslation(xOffset, yOffset);
CGAffineTransform scale = CGAffineTransformMakeScale(scaleAmount, scaleAmount);
view.transform = CGAffineTransformConcat(shift, CGAffineTransformConcat(scale, unshift));
}
It's probably more general than what you need, and you could do it simpler, but this should work too. Just change the point to something that looks like the center of the arrow.

CATransform3DMakeRotation Setting AnchorPoint and position. iOS7 View position mistake

CATransform3DMakeRotation Setting AnchorPoint and position
iOS7 View position mistake...
but iOS8 and iOS9 dont have this problem..
why?
-(void)viewDidAppear:(BOOL)animated
{
[self setAnchorPoint:CGPointMake(0.5, 1) forView:self.chieldImageView];
}
-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x,
view.bounds.size.height * anchorPoint.y);
CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x,
view.bounds.size.height * view.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
CGPoint position = view.layer.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
view.layer.position = position;
view.layer.anchorPoint = anchorPoint;
}
This is probably due to the use of auto layout, on iOS8 and major they fixed it.
There are not so many solution, one is to keep the view you are transforming inside a container view. You use constraints on the container view to position it and in the contained (need to be transformed view) you just add it as a subview by keeping the -translatesAutoresizingMaskIntoConstraints to YES.
Check on Matt book.

iOS CGAffineTransformScale keep left anchor

I am using CGAffineTransformScale to scale down my UITableView, it is scaling it down correctly but i can't seem to set the anchor point correctly.
self.myTableView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.8, 0.8);
If I don't set the anchor point it scales it down from the center but as my requirement I need to keep the left top corner point fixed. For this I've used this
self.myTableView.layer.anchorPoint = CGPointMake(0, 0);
self.myTableView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.8, 0.8);
But this doesn't set the anchor correctly.. One more thing I haven't used AutoLayout
Please can anyone help me out on this…? thanks in advance..
Try this
[self setAnchorPoint:CGPointMake(0, 0.5) forView:recognizer.view]; // for left anchor point
and here setAnchorPoint
-(void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view
{
CGPoint newPoint = CGPointMake(view.bounds.size.width * anchorPoint.x,
view.bounds.size.height * anchorPoint.y);
CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x,
view.bounds.size.height * view.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
CGPoint position = view.layer.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
view.layer.position = position;
view.layer.anchorPoint = anchorPoint;
}

Calculate rotation angle for anchor point

I got stuck with a problem where I need to reposition views to predefined locations.
All views have a UIPanGestureRecognizer and a UIRotationGestureRecognizer and are positioned/rotated inside the controllers view. Upon a certain event the views should move to a new position with a new rotation angle.
Everything works fine but a soon as one of the gesture recognizer was active and thus the anchorPoint has changed repositioning/rotation fails.
Here is my method I try to use to take the shift in the anchorPoint into account.
- (CGPoint)centerPointWithInVisibleAreaForPoint:(CGPoint)point
{
CGPoint anchorP = self.layer.anchorPoint;
anchorP.x -= 0.5;
anchorP.y -= 0.5;
CGRect rect = self.bounds;
CGFloat widthDelta = CGRectGetWidth(self.bounds) * anchorP.x;
CGFloat heightDelta = CGRectGetHeight(self.bounds) * anchorP.y;
CGPoint newCenter = CGPointMake(point.x + widthDelta, point.y + heightDelta);
return newCenter;
}
The controller asks for the corrected center point and sets the center value of the view. Afterwards the rotation transform is set using CGAffineTransformConcat(view.transform, CGAffineTransformMakeRotation(differenceAngle)).
I think the problem is caused by the fact that the predefined target angle is based on a rotation around the center which is obviously different when rotated around a different anchorPoint, but I don't know how to compensate for that.
The only solution I found (and it is after all the most easiest one) is to reset the anchorPoint to 0.5/0.5 and correct the position accordingly.
- (void)resetAnchorPoint
{
if (!CGPointEqualToPoint(self.layer.anchorPoint, CGPointMake(0.5, 0.5))) {
CGFloat width = CGRectGetWidth(self.bounds);
CGFloat height = CGRectGetHeight(self.bounds);
CGPoint newPoint = CGPointMake(width * 0.5, height * 0.5);
CGPoint oldPoint = CGPointMake(width * self.layer.anchorPoint.x, height * self.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, self.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, self.transform);
CGPoint position = self.layer.position;
position.x += (newPoint.x - oldPoint.x);
position.y += (newPoint.y - oldPoint.y);
[CATransaction setDisableActions:YES];
self.layer.position = position;
self.layer.anchorPoint = CGPointMake(0.5, 0.5);
[CATransaction setDisableActions:NO];
}
}

How to scale (zoom) a UIView to a given CGPoint

I've spent a lot of time trying to find a way to use CGAffineScale to transform a view to a given point, including messing around with anchor points, moving the centre of a view before and after transforming and comprehensive Googling. I am aware this would be a lot simpler with a UIScrollview; but I know it's technically possible to do without one, and it's become a splinter in my mind.
This answer gets remarkably close to what I want to achieve, but the answer only gives details on how to zoom to a given corner (instead of a given point) by cleverly moving the centre to the corner opposite the one you want to zoom in to.
How can I modify mvds' code to scale a UIView to any given point in a UIView?
CGFloat s = 3;
CGAffineTransform tr = CGAffineTransformScale(self.view.transform, s, s);
CGFloat h = self.view.frame.size.height;
CGFloat w = self.view.frame.size.width;
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
self.view.transform = tr;
self.view.center = CGPointMake(w-w*s/2,h*s/2);
} completion:^(BOOL finished) {}];
There are 2 steps involved: First you scale up the view you want to zoom in to. Then you set the center of this blown up view such that the part you want to see ends up in the middle of the view.
You should draw this out on paper and the formulas will follow: (untested)
CGFloat s = 3;
CGPoint p = CGPointMake(100, 200);
CGAffineTransform tr = CGAffineTransformScale(self.view.transform, s, s);
CGFloat h = self.view.frame.size.height;
CGFloat w = self.view.frame.size.width;
[UIView animateWithDuration:2.5 delay:0 options:0 animations:^{
self.view.transform = tr;
CGFloat cx = w/2-s*(p.x-w/2);
CGFloat cy = h/2-s*(p.y-h/2);
self.view.center = CGPointMake(cx, cy); //was: (w*s/2,h-h*s/2);
} completion:^(BOOL finished) {}];
I actually ran into this very same problem myself. To fix it, all I did was change the anchor point of the view I was scaling because CGAffineTransforms are performed on the view in relation to its anchor point, so depending on where the anchor point is, the transform will scale, translate, or rotate the view differently. Here's the basic idea:
CGPoint pointToScaleTo = CGPointMake(x, y); //Just enter the coordinates you
//want to scale your view towards
CGFloat viewWidth = self.view.bounds.size.width;
CGFloat viewHeight = self.view.bounds.size.height;
CGFloat scaleFactorX = ...;
CGFloat scaleFactorY = ...;
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scaleFactorX, scaleFactorY);
[UIView animateWithDuration:2.5f delay:0.0f options:0 animations:^{
//I divide the x and y coordinates by the view width and height
//because the anchor point coordinates are normalized to the range
//0.0-1.0.
self.view.layer.anchorPoint = CGPointMake(pointToScaleTo.x/viewWidth, pointToScaleTo.y/viewHeight);
//Now that the anchor point has been changed, apply the scale transform
self.view.layer.transform = scaleTransform;
} completion:^(BOOL finished) {}];

Resources