Move and resize UILabel with CGAfficeTransform - objective-c

Basically I want to move a UILabel up 20px and resize it to 55% of it's original size.
=> x stays the same, y,height, width decrease.
What I came up is following :
//_line a UILabel*
CGFloat scaleFactor = 0.55f;
[UIView animateWithDuration:1.0 animations:^{
CGAffineTransform transform = CGAffineTransformMakeTranslation(0, -20);
transform = CGAffineTransformScale(transform, scaleFactor, scaleFactor);
_line.transform = transform;
}];
Unfortunately I don't get the expected result. It (slightly) moves up but also moves to the right.
What am I missing ?

The problem is that you're using Auto Layout. Auto Layout and view transforms are enemies of one another. You perform the transform, but then Auto Layout kicks in and changes the frame of the label essentially back to what it was.

The problem is that you're overwriting the transform. You initially set transform to the translation transformation, and then before anything has happened you reset it to the scale transformation. So all it's doing is the scale action.
Instead you need to combine the two matrices and store their combination into transform. Try this:
CGFloat scaleFactor = 0.55f;
[UIView animateWithDuration:1.0 animations:^{
CGAffineTransform translationTransform = CGAffineTransformMakeTranslation(0, -20);
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scaleFactor, scaleFactor);
CGAffineTransform totalTransform = CGAffineTransformConcat(translationTransform, scaleTransform);
_line.transform = totalTransform;
}];

This did the job fob me : a second translation
CGFloat scaleFactor = 0.55f;
CGFloat x_delta = _line.frame.size.width * (1-scaleFactor);
CGFloat y_delta = _line.frame.size.height * (1-scaleFactor);
[UIView animateWithDuration:1.0 animations:^{
CGAffineTransform transform = CGAffineTransformMakeTranslation(0, -20);
transform = CGAffineTransformScale(transform, scaleFactor, scaleFactor);
transform = CGAffineTransformTranslate(transform, -x_delta, -y_delta);
_line.transform = transform;
}];

Related

How do i shrink an image horizontally using CGAffineTransform?

I've been using CABasicAnimation to move around images. Now I need to take a view and shrink it horizontally. On the web I see some people using CGAffineTransform to shrink/grow images proportionally. I need the view to shrink horizontally ONLY. See image below:
Any help with this would be greatly appreciated!
CGAffineTransformMakeScale(sx,sy) will do the work.
CGAffineTransform a = CGAffineTransformMakeScale(0.4, 1.0);
editingView.transform = a;
You can use [UIView animateWithDuration:animations:completion:]; if you want it to be animated.
CGAffineTransform a = CGAffineTransformMakeScale(0.4, 1.0);
[UIView animateWithDuration:0.5
animations:^{
editingView.transform = a;
}
completion:^(BOOL finished) {
/* do something after the animation */
}];

UIButton rotation animation not rotating back with CGAffineTransformMakeRotation

I have a button (openMenu) that I am animating down (works fine) and rotate (works the first time) with a "drawer". The first time it rotates it works.. but when I try to rotate again it wigs out and hides the image and shows the button title? Any ideas of why? I need it to just rotate back another 45 degrees. Don't know why it would do this.
Also - see GIF image below so you see what is happening.
- (void)viewDidLoad
{
[super viewDidLoad];
draw1 = 0;
scrollView.frame = CGRectMake(0, -200, 768, 200);
[scrollView setContentSize:CGSizeMake(768, 200)];
openMenu.frame = CGRectMake(680, 100, 55, 55);
}
- (IBAction)openMenu:(id)sender {
if (draw1 == 0) {
draw1 = 1;
CGRect optionsDrawer = scrollView.frame;
CGRect optionsButton = openMenu.frame;
optionsDrawer.origin.y += 200;
optionsButton.origin.y += 200;
[UIView animateWithDuration:0.5
animations:^{
scrollView.frame = optionsDrawer;
openMenu.frame = optionsButton;
openMenu.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(45));
}];
} else {
draw1 = 0;
CGRect optionsDrawer = scrollView.frame;
CGRect optionsButton = openMenu.frame;
optionsDrawer.origin.y -= 200;
optionsButton.origin.y -= 200;
[UIView animateWithDuration:0.5
animations:^{
scrollView.frame = optionsDrawer;
openMenu.frame = optionsButton;
openMenu.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(45));
}];
}
}
Do like this, i am using layers to animate, it is easy, once u rotate, dont need to rotate again, just brings back to original state. I did like this it works for me, just try this.
since i am using layers add "QuartzCore" library and import this
#import<QuartzCore/QuartzCore.h> //include this
if (draw1 == 0)
{
....//your code
[UIView animateWithDuration:0.1 animations:^{
detailButton.layer.transform = CATransform3DMakeRotation((180) * 45, 0, 0, 1);
}];
}
else
{
....//your code
[UIView animateWithDuration:0.1 animations:^{
detailButton.transform = CGAffineTransformIdentity; //brings back to original position by animating
}];
}
hope this helps u :)
If you want to rotate the button back - you need to provide negative number as the value for CGAffineTransformMakeRotation().
Here is the snippet from Apple Docs:
CGAffineTransformMakeRotation()
Returns an affine transformation matrix constructed from a rotation
value you provide.
CGAffineTransform CGAffineTransformMakeRotation ( CGFloat angle );
The angle, in radians, by which this matrix rotates
the coordinate system axes. In iOS, a positive value specifies
counterclockwise rotation and a negative value specifies clockwise
rotation. In OS X, a positive value specifies clockwise rotation and a
negative value specifies counterclockwise rotation.
Hope this helps!

iOS view transform animation

I'm probably missing something simple, but trying to do a simple "Ken Burns Effect" with an image view.
First the code:
[UIView animateWithDuration:20
delay:2
options:UIViewAnimationCurveLinear
animations:^{
CGAffineTransform move = CGAffineTransformMakeTranslation(40, 40);
CGAffineTransform zoom = CGAffineTransformMakeScale(1.2, 1.2);
CGAffineTransform transform = CGAffineTransformConcat(zoom, move);
self.imageView.transform = transform;
}
completion:^(BOOL finished){
NSLog(#"Done");
}];
I expected this to start with the image view at normal scale and expand it to 120% of the size over 20 seconds. What actually happens is that it starts out immediately smaller than normal size, then expands to normal size.
If I use the reciprocal of the scale value, it starts out zoomed in and then zooms out to normal scale which is the opposite of the effect I want.
Any ideas?
Ok, this actually worked and does what I want.
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
transformAnimation.duration = 20.0;
transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
transformAnimation.removedOnCompletion = NO;
transformAnimation.fillMode = kCAFillModeForwards;
CATransform3D xform = CATransform3DIdentity;
xform = CATransform3DScale(xform, 1.2, 1.2, 1.0);
xform = CATransform3DTranslate(xform, 60, -60, 0);
transformAnimation.toValue = [NSValue valueWithCATransform3D:xform];
[self.imageView.layer addAnimation:transformAnimation forKey:#"transformAnimation"];
It sounds like the view is being re-laid out by its parent view in response to the change in transform, casing it to be scaled down to the end result of the transform as soon as the transform is set in the animation block. The key is that your first attempt makes changes directly to the view, while the second approach works with the layer.
Have you try starting form the current transform of your imageView ?
[UIView animateWithDuration:20
delay:2
options:UIViewAnimationCurveLinear
animations:^{
CGAffineTransform trans = self.imageView.transform;
CGAffineTransformTranslate(trans, 40, 40);
CGAffineTransformScale(trans, 1.2, 1.2);
self.imageView.transform = trans;
}
completion:^(BOOL finished){
NSLog(#"Done");
}];

Hide and show scrollview with animation

In my app I have a scrollview and when I press a button it is hidden when I press again it shows up.
I use scrollview.hidden = YES (or NO) to do it.
But I want to do it with an animation. For example, it may disappear from the bottom of the screen by moving and shows up with the same way. How can I do that?
edit:
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = bottomScroller.frame;
if(Frame.origin.y == 380){
Frame.origin.y = 460;
}else{
Frame.origin.y = 380;
}
bottomScroller.frame = Frame;
[UIView commitAnimations];
This solved my problem...
You may check UIView animations. It's pretty easy. For example to animate translation you may use something like:
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = yourView.frame;
Frame.origin.y = 0;
yourView.frame = Frame;
[UIView commitAnimations];
Then to move it back:
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = yourView.frame;
Frame.origin.y = 100;
yourView.frame = Frame;
[UIView commitAnimations];
Changes in frame, alpha and some other parameters will be automatically animated.
You can use animations like so:-
[UIView animateWithDuration:2.0 animations:^{
[scrollview setframe:CGRectMake(xpos, ypos, width, height)];
}];
If you want to slide the scrollview on or off the screen set its y position - the bottom of the view is you want to hide it, the normal y position if you want to show it.
The 2.0 is an animation length, this can be changed to whatever you need it to be!
You can do this by using simple view animations. Here's an example of how you might do this:
// myScrollView is your scroll view
-(void)toggleShow{
CGFloat targetAlpha = myScrollView.alpha == 1 ? 0 : 1;
CGFloat yPosition = targetAlpha == 1 ? 0 : self.view.frame.size.height;
[UIView animateWithDuration:1.0 animations:^{
myScrollView.frame = CGRectMake(myScrollView.frame.origin.x, yPosition, myScrollView.frame.size.width, myScrollView.frame.size.height);
myScrollView.alpha = targetAlpha;
}];
}
targetAlpha will always be the opposite of the current state (1 or 0), and if it's 0 then the y position will be set to the bottom of the parent view. Using the new-school UIView animations API with blocks we can execute these changes to the scroll view over 1 second (in my example).
ScrollView appers from down side of screen with animation. I think this up-animation is what you want.
// ScrollView appearing animation
- (void)ScrollViewUpAnimation
{
// put the scroll view out of screen
CGRect frame = ScrollView.frame;
[self.view addSubview:ScrollView];
ScrollView.frame = CGRectMake(0, 460, frame.size.width, frame.size.height);
// setting for animation
CGPoint fromPt = ScrollView.layer.position;
CGPoint toPt = CGPointMake(fromPt.x, fromPt.y - frame.size.height - 44);
CABasicAnimation* anime =
[CABasicAnimation animationWithKeyPath:#"position"];
anime.duration = 0.2;
anime.fromValue = [NSValue valueWithCGPoint:fromPt];
anime.toValue = [NSValue valueWithCGPoint:toPt];
// change the position of Scroll View when animation start
[ScrollView.layer addAnimation:anime forKey:#"animatePosition"];
ScrollView.layer.position = toPt;
}

Animate Rotation/Scale/Translate of UIImage at the same time

I am new to objective-c and I want to add an image to the screen, tweening it like in AS3, moving it from one end to the other of the screen while rotating around its own center point.
I tried with
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
// TRANSFORM SCREENSHOT
screenShotView.transform = CGAffineTransformRotate(screenShotView.transform, -M_PI * 0.05);
screenShotView.transform = CGAffineTransformScale(screenShotView.transform, 0.6, 0.6);
screenShotView.transform = CGAffineTransformTranslate(screenShotView.transform,
self.webView.frame.origin.x,
self.webView.frame.origin.y - self.webView.frame.size.height * 0.3
);
but with this code the image rotates around the center of the TransformIdentity. So while rotating and moving the rotation gets out of controll and the image isn't exactly at the position I loved it to be.
What is the right way to rotate and translate at the same time, translating the rotation center with the image?
and at least after transformation I want to add a close button to the right upper corner of the image. for that I need the new coordinates of the corner, too.
thnx!
I now ended with the following code, but I still don't know if this is the state of the art solution.
CGAffineTransform translate = CGAffineTransformMakeTranslation(self.webView.frame.origin.x,self.webView.frame.origin.y - self.webView.frame.size.height * 0.25);
CGAffineTransform scale = CGAffineTransformMakeScale(0.6, 0.6);
CGAffineTransform transform = CGAffineTransformConcat(translate, scale);
transform = CGAffineTransformRotate(transform, degreesToRadians(-10));
[UIView beginAnimations:#"MoveAndRotateAnimation" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:2.0];
screenShotView.transform = transform;
[UIView commitAnimations];
IOS 7's preferred way to do this would be using a block object. It has several advantages compared to the 'older' way of animating. Especially that it can make use of multi-core and video co-processing. Also the 'built-in' call back part (the completion part) is very useful, as it keeps any necessary state information and links to objects as needed.
CGAffineTransform translate = CGAffineTransformMakeTranslation(self.webView.frame.origin.x,self.webView.frame.origin.y - self.webView.frame.size.height * 0.25);
CGAffineTransform scale = CGAffineTransformMakeScale(0.6, 0.6);
CGAffineTransform transform = CGAffineTransformConcat(translate, scale);
transform = CGAffineTransformRotate(transform, degreesToRadians(-10));
// animation using block code
[UIView animateWithDuration:2.0
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
screenShotView.transform = transform;
}completion:^(BOOL finished){
// do something if needed
}];