iOS - rotating an UIImageView based on X,Y orientation - ios

I've subclassed a UIView as an avatar-object, which contains an icon (UIImageView), name (UILabel) and ID (UILabel). Depending on the orientation X,Y coordinates, I want the icon to be rotated. For example, say orientation.X = 1 and orientation.Y = 1 would give 45 degrees angle. X and Y could be anything between -1 and 1.
I'm not sure how it is calculated mathematically nor the cocoa API calls for it. Any ideas where to start?

for smoothness i added an animation:
- (void)rotateView:(UIView *)view withDuration:(NSTimeInterval)duration andRadians:(CGFloat)radians
{
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformMakeRotation(radians);
view.transform = transform;
// Commit the changes
[UIView commitAnimations];
}
EDIT:
for other angles you need to create your own rotation matrix.
How rotation matrix works
Read here how to create a custom affine transformation in Objective-c
Hope this helps.

You need to look into the trigonometric functions - specifically acos and asin.
This article may be helpful.

Related

Imageview changing position when transform is applying?

I had an IPhone application in which i want to transform my image view to its double size without changing the position of the image view.(i.e. the centre need not be changed)I am doing like this
CGAffineTransform firstTransform = bg.transform;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.5];
bg.transform = CGAffineTransformScale(bg.transform,2,2);
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.5];
bg.transform = firstTransform;
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
But when transforming its position gets changed.so
Now i am doing like this to do not change the position of the image view.i want the image view to be transformed to the double size on click with an animation like this
animation on the red button when clicking next
can anybody guide me on this?
Make sure the anchor point is set to the centre, bearing in mind when setting the anchor point the value has to be between 0 and 1: 0 being the left/top side and 1 being the right/bottom side. So to set the anchor point to the middle, set it to 0.5 on both the X and Y axis:
[itemName.layer setAnchorPoint:CGPointMake(0.5, 0.5)];
Then when you scale the object, it should scale up from around the centre point.
I also suggest using animateWithDuration:completion. The code will become much simpler:
[UIView animateWithDuration:1.0f animations:^{
[bg setTransform:CGAffineTransformScale(bg.transform, 2.0, 2.0)];
} completion ^{
[UIView animateWithDuration:1.0f animations:^{
[bg setTransform:CGAffineTransformScale(bg.transform, 0.5, 0.5)];
];
}];
Hope this helps you achieve the desired effect!
Make sure that you are not using auto layout. To disable that open your xib, click on first tab in the right panel, uncheck the Use Auto Layout under Interface Builder Document. Screen shot is attached for help.

Get UIImages from UIViewAnimation

I have some simple animation code:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
image.transform = transform;
// Commit the changes
[UIView commitAnimations];
It is possible to get each frame of the animation as uiimages?
You cannot get each frame as UIImages (except if you used UIGraphicsGetCurrentContext at a very fast rate on the frame of the animating view, and I'm not even sure if that would work), but with a Core Animation, you can access the presentationLayer property of a CALayer, which (from the CALayer Class Reference):
Returns a copy of the layer containing all properties as they were at the start of the current transaction, with any active animations applied.
Hope this helps!

Intersection Of Two UIViewImages

How can I determine if two uiviewimages intersect. I want to do an auto snap feature. When the small image intersects with the big image or close to it (Lets says the distance<=x), I want the small image automatically snap(connect) to the big image at the point where they intersect.
CGRect bigframe = CGRectInset(bigView.frame, -padding.x, -padding.y);
BOOL isIntersecting = CGRectIntersectsRect(smallView.frame, bigFrame);
The previous two posters have been on the right track with CGRectIntersectsRect.
BOOL isIntersecting = CGRectIntersectsRect(smallImage.frame, largeImage.frame);
if(isIntersecting){
//Animate the Auto-Snap
[UIView beginAnimation:#"animation" context:nil];
[UIView setAnimationDuration:0.5];
smallImage.frame = largeImage.frame;
[UIView commitAnimations];
}
Basically what this says that if the two images are intersecting, the small image frame snap to the larger image over 0.5 seconds.
You don't have to animate it though; you could just make it instantaneous by removing all code except for smallImage.frame = largeImage.frame;. However, I recommend the animation way.
Hope this helps.
-------EDIT--------
You could use the code:
BOOL isIntersecting = CGRectIntersectsRect(smallImage.frame, largeImage.frame);
if(isIntersecting){
//Animation
[UIView beginAnimation:#"animation" context:nil];
[UIView setAnimationDuration:0.5];
smallImage.center = CGPointMake(largeImage.center.x, largeImage.center.y);
//If you want to make it like a branch, you'll have to rotate the small image
smallImage.transform = CGAffineTransformMakeRotation(30);
//The 30 is the number of degrees to rotate. You can change that.
[UIView commitAnimations];
}
Hope this fixed your problem. Remember to up vote and pick as the answer if this helped.
-------EDIT---------
One last thing. I said that the "30" in CGAffineTransformMakeRotation(30) stood for 30 degrees, but that is incorrect. The CGAffineTransformMakeRotation function takes its parameter in radians, so if you wanted 30 degrees you could do this:
#define PI 3.14159265
CGAffineTransformMakeRotation(PI/6);
You can use the CGRectIntersectsRect method to check for frames:
if (CGRectIntersectsRect(myImageView1.frame, myImageView2.frame))
{
NSLog(#"intersected")
}

iOS Animation 1+2 = 3. 3-2 != 1

iPad - iOS 5.1 - Xcode 4.3.2
When the keyboard pop ups I animate the y origin of my UIImageView up by "x"
When the keyboard goes down, i animate it back down by the same "x"
So the keyboard pops up, the image goes up by X, the keyboard comes down, the image goes down by x, but it doesn't end up in the same place!. You go up 60, down 60, and you're not in the same place! it's further down, as if the coordinate system changed between the appearance of the keyboard and the disappearance of it. It absolutely drives me crazy. I can't understand why this happens.
//add gesture recognizer when keyboard appears
-(void)keyboardWillShow:(NSNotification *) note {
[self.view addGestureRecognizer:tapRecognizer];
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3f];
[UIView setAnimationCurve:UIViewAnimationOptionCurveEaseInOut];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix: Logo Image
CGAffineTransform moveLogo = CGAffineTransformMakeTranslation(0, -60);
self.logoImageView.transform = moveLogo;
// Commit the changes
[UIView commitAnimations];
}
//add gesture recognizer when keyboard appears
-(void)keyboardWillHide:(NSNotification *) note {
[self.view removeGestureRecognizer:tapRecognizer];
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3f];
[UIView setAnimationCurve:UIViewAnimationOptionCurveEaseInOut];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix: Logo Image
CGAffineTransform moveLogo = CGAffineTransformMakeTranslation(0, 60);
self.logoImageView.transform = moveLogo;
// Commit the changes
[UIView commitAnimations];
}
That's because you are not translating it, when you use CGAffineTransformMakeTranslation you are saying Give me these coordinates not give me this offset. In other words, make translation gives you the translation from the identity matrix. The function you want is CGAffineTransformTranslate. This will apply the translation to the current transform (passed as the first argument).
the transform property is not cumulative. You are not doing what you think you're doing. You are calculating the new transform from your identity, not from the current transform.
Instead of:
CGAffineTransform moveLogo = CGAffineTransformMakeTranslation(0, 60);
self.logoImageView.transform = moveLogo;
Try:
self.logoImageView.transform = CGAffineTransformIdentity;
Instead of messing around with Core Graphics you might want to animate simple view properties, like frame or size. For example:
[self.logoImageView.center = CGPointMake(self.logoImageView.center.x,
self.logoImageView.center.y + 60);
Do this between beginAnimations and commitAnimations

CGAffineTransformMakeTranslation: How to apply two animations at once

I have a view which I would like to transform in two ways. First I'd like to move it on its y-axis. Then, I'd like to zoom in on it.
However, when I use the following code, the object is first moved and then moved back to its original position while being zoomed.
Is there a way to apply the two transformation at once without cancelling the first?
Sorry if this is basic, but any help would be very much appreciated!
[UIView animateWithDuration:animationDuration
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
currentCover.transform = CGAffineTransformMakeTranslation(0, 0-keyboardTop+35);
}
completion:^(BOOL finished) {
[UIView animateWithDuration:animationDuration
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
[currentCover setTransform:CGAffineTransformMakeScale (1.3, 1.3)];
}
completion:^(BOOL finished) { }
];
}
];
You should multiply one transform by the other. Each transform (scale and translate) are transform matrices. To combine them, simply multiple one by the other before using it. The order of the multiplication determines the order that the tranforms are applied
I'd similar issue where my view moves back to original position.
Documentation of CGAffineTransformMakeTranslation reads "it constructs a new translation matrix from x and y values that specify how much to move the origin." I don't think it applies actual transformation.
I think you'd rather apply translation by calling CGAffineTransformTranslate(). At least it works for me!!
Here we are creating the two changes (CGAffineTransform's) you want to do together, and apply the transformation to the view.
CGAffineTransform translate = CGAffineTransformMakeTranslation(0, 0-keyboardTop+35);
CGAffineTransform scale = CGAffineTransformMakeScale(1.3, 1.3);
CGAffineTransform transform = CGAffineTransformConcat(translate, scale);
[UIView animateWithDuration: animationDuration
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
currentCover.transform = transform;
}completion:^(BOOL finished){
}];

Resources