Rotate a UIView in 2D, not 3D - ios

When I use either of the following pieces of code, the button rotates in 3D rather than 2D (flat against the screen). How can I avoid the 3D behavior? Here's what the button looks like during the rotation:
CGAffineTransform rotationTransform = CGAffineTransformIdentity;
rotationTransform = CGAffineTransformRotate(rotationTransform, (offset/(180.0 * M_PI)));
button.transform = rotationTransform;
.
button.transform = CGAffineTransformRotate(CGAffineTransformIdentity, (offset/(180.0 * M_PI)));
.
button.transform = CGAffineTransformMakeRotation(offset/(180.0 * M_PI));

Here's the answer from an Apple employee:
When you set a transform the frame becomes less well-defined, to the
point that you should no longer use it to size or position a view. Try
using the center property instead, your probably not getting a 3D
rotation, but a distortion due to the compounding effect of setting
the frame and trnsform.

I met the same problem which is really annoying, and I got it settled at last, though still have no idea why.
I got unexpected 3D rotations when I tried to perform a 2D rotation in "viewDidLayoutSubviews" method with
double radius = (degree / 180.0) * M_PI;
uiImageView.transform = CGAffineTransformMakeRotation(radius);
My solution is to perform transforming elsewhere other than "viewDidLayoutSubviews" and it is working perfectly.
Interestingly, when the annoying 3D rotation happens, and I keep orienting my iPhone for a while, the 3D rotation will disappear suddenly and 2D rotation will come back and take the place, but the image stays at a distorted shape. I guess maybe iOS is doing some internal transforming in "viewDidLayoutSubviews" and things get messed up if we impose additional transforming on it. However, my guess cannot explain why it disappears after a while. I also tried to NSLog the members of "uiImageView.transform", say, "a, b, c, d, tx, ty" in "viewDidLayoutSubviews" but got no clue.
SOLUTION: Check your code to see if you are performing the rotation in "viewDidLayoutSubviews" or some similar method, and if yes, try to move it out to elsewhere and cross fingers.

Related

Flipping image after rotation issue (need to do both, only does one)

I have a UIImage on my storyboard, and I have just rotated it( i can rotate it any number of degrees). The code for the rotation is below:
let DegreesFloat = Double(-Degrees) * M_PI/180
self.imageView.transform = CGAffineTransformMakeRotation(CGFloat(DegreesFloat))
By the way, degrees in the first line of code, is an integer I enter into a text field. When the view loads, I have this...
self.imageView.transform = CGAffineTransformMakeScale(1, -1);
to keep the image upside down, cause that's just how I need it to be. The issue is that when I rotate the image, it cancels out the flip, and flips it back to its original flip (without the 2nd paragraph of code). I need it to keep it's upside down flip, while performing it's rotation.
When I add the flip code after the rotate code, it just cancels out the rotate code. I have no idea how to do this, but I just need it to stay upside down, while correctly performing a rotation, and NOT flipping itself back to its original right-side up orientation.
I think what you are asking is how to make multiple transform commands together. The transformations are actually a matrix telling the image later what to do. Use a CGAffineTransformConcat to apply multiple transformations. Refer to the Apple documentation

How to rotate a view in place after transform as been applied?

I'm using a variant of this code to slighty rotate a UIButton about its center:
CGFloat jiggleAngle = (-M_PI * 2.0) * (1.0 / 64.0);
self.transform = CGAffineTransformRotate(self.transform, jiggleAngle);
This code generally works as expected and rotates the button in-place, about 12 degrees counter-clockwise. However, this only works if I do not reposition the button inside my layoutSubviews method. If I do any repositioning of the button at all from its initially laid-out location, the attempt to rotate above results in the button's disappearance. If the angle I choose for rotation is an exact multiple of 90 degrees, the rotation works somehow even after a move in layoutSubviews.
I understand that my button's transform is being altered in layoutSubviews and this results in the subsequent weirdness when I attempt to rotate it with the above code. I have currently worked around this problem by placing the button I wish to rotate inside another UIView and then moving that view around as desired, but I'd like a better solution that doesn't require redoing my screen layouts.
How can I adjust/alter my button's transform after a move, so that this rotation code continues to work as expected?
The problem you are facing is that a view's frame is "undefined" if it's transform isn't the identity transform.
What you should do is use the view's center property to move it around. That works even if you've changed it's transform.
You can also apply a rotation to the view's layer instead of the view (although be aware that the layer transform is a CATransform3D, a 4x4 transformation matrix instead of a 3x3, so you need different methods to manipulate it.)

Rotate UILabel On Clockface

Is it possible to rotate UILabels or similar about a clockface?
For example, if I had an array of numbers from one to twelve, it would render as such in a circular manner. However, with a touch event I could move the labels about the face of the clock i.e. I could move 12 in a rightward motion until it reached 6, with all other numbers remaining in their positions.
I have considered UIPicker, but that follows a 'top to bottom' approach. I need a solution to move the label about a point while maintaining the order of the other labels.
It's simply a matter of opposing rotation transforms. Rotate the clock face while at the same time rotating all the subview numbers the same amount in the opposite direction.
Recommended:
1 Clock without small & Big handle (As Image) set it in ImageView.
2 Another two image view one for Small hand another one for Big hand.
3 Rotate the hands(UIImageView) by using the below code as you needed.
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
UIImageView *smallHand = set your smallHand image view here;
UIImageView *bigHand = set your bigHand image view here;
// Small hand
CGAffineTransform smallHandTransform = CGAffineTransformRotate(self.transform, (DEGREES_TO_RADIANS(1)));
// Big hand
CGAffineTransform bigHandTransform = CGAffineTransformRotate(self.transform, (DEGREES_TO_RADIANS(1*0.60)));
// Apply rotation
smallHand.transform = smallHandTransform;
bigHand.transform = bigHandTransform;
I knew that question was rotating the label, if you need it apply this transform on UILabel.
I hope somebody will make use of this idea. Good luck :)
Here is the example project

Distorting UIImage into Parallelogram

I have a UIImage that results from a function. It's something like the following.
image1.image = [self reflectedImage:img];
where image1 is a UIImage control. Before plugging it into image1, I want to further distort it to the right or left a little into a parallelogram as shown below. So I just want to relocate point c and d.
I've read several dozen articles here and there. I'm not sure if I can do it with CGAffineTransformMake. This web page suggests that I could. Unfortunately, there is no sample project to see how it works. Unfortunately, I haven't found a single web site that shows me how to distort a simple rectangle image into a parallelogram. So what is the easiest way of doing it? Do I need to create a layer so that I can use CATransform3D?
Thank you for your help.
I found out an alternative way which is way simpler than the other in this topic. Just apply this transformation to your view:
imgView.transform = CGAffineTransformMake(1.0, 0.0, proportion, 1.0, 0.0, 0.0);
where proportion is between -1 and 1
This is called a shear transformation, look at the link below for more
http://iphonedevelopment.blogspot.it/2008/10/cgaffinetransform-11-little-more.html
What you have to do is give your UIImageView some perspective. By default a layers transform do not have perspective, so you must also setup this: transform.m34 = 1.0 / -2000;
Also change the anchorpoint of your view so that it rotates along the top edge of the view. For you it becomes (0,0.5).
The perspective gives it that parallelogram look as if the view has depth (its also called 2.5D as its not pure 3D animation, its pseudo 3D). Set the anchor point so that it rotates along that edge and finally give it an angle. i.e. rotate by how much?
// Rotate by 30 degrees
CGAffineTransform rotationTransform = CGAffineTransformIdentity;
rotationTransform = CGAffineTransformRotate(rotationTransform, DegreesToRadians(30));
swingView.transform = rotationTransform;
all of this will give you what you want...

UI equivalent of setFrameCenterRotation?

I have been coding for MacOs for months and now exploring iOS. It's a bit confusing.
In MacOS, I have a NSImageView I can rotate using setFrameCenterRotation. One outlet, one call, and the work is done.
I suppose there is an equivalent in iOS but I could only find code examples using animation and a lot of calculation (certainly to make "nice" game-like features on this tiny screen).
I don't want any animation, just my ...UIImageView to rotate in one block from a given number of degrees.
Can it be done?
Any suggestion really welcome!
Regards,
B.
You probably want to set the view's transform property to a rotation transform. Example:
CGFloat radians = degrees * M_PI / 180;
myImageView.transform = CGAffineTransformMakeRotation(radians);
UIImageView inherits the transform property from UIView, so you will need to consult the UIView Class Reference for documentation.

Resources