Flip Animation Using Core Animation Showing Reversed Contents - ios

Here is the result that I get:
If I set the doubleSided property of layer 4 as No, the whole layer disappears. I know that already. But then, how can I show yet with correct content orientation?

Do the animation in two parts. At the halfway point, when the layer is side-on to the camera so you can’t see it, flip the layer the other way around and move the anchor point to the other side, and swap out the contents of the layer if you need to.
Unfortunately, I don’t have any sample code, because the last time I did this was on iOS 4, and the pile of hacks view-based animations that I was using don’t appear to work on layers any more. You could post your own code and accept your own answer if you want.

Related

CALayer rotation appears to 'lift' it's child above the surface

Here is the iPad Simulator with four nested UIViews, drawing a custom background, and an inner UILabel. I am rotating the top UIView's CALayer, by getting it's layer and setting transform with a rotateY CATransform3D, animated on a separate thread (but the changes to transform are being sent on the main thread, naturally):
Note- this animation does not loop correctly, hence it appears to bounce.
The layers do animate as a whole, but curiously, the first child and it's descendants appear to be floating above the UIView with the transform applied!
The UIViews themselves are children in another UIView, which has a red background. There are no other transformations being applied anywhere else.
The positions for each UIView were set using setFrame initially at the start.
What is causing this strange behaviour, and how can I ensure the child UIViews transform with their parent, giving a flat appearance to the surface as a whole?
Well. Perhaps unsurprisingly I was doing something silly, but since I'd not used CALayer transforms before, I didn't know if things were acting up. I had overridden layoutSubviews on the UIViews I was creating, and the act of rotating the CALayer was triggering this call and then pushing the child components frame around, due to a bug.
The problem is that CALayers don't actually do 3D perspective by default. In order to do that you need to make a minor change to the layer's transform (which is of type CATransform3D)
You want to change the .m34 field of the transform to a small negative value. Try -1/200 to -1/500 as a starting range. If I remember correctly it should be the negative of 1 over the image height/width.
Change the .m34 property of the layer that you want to appear to "come off the page" and rotate in 3D. When you do that the Z setting of the layer does matter, and will both make closer layers bigger and also make layers that are further away disappear behind other things.
I suggest you do a Google search on "CATransform3D m34" for more information. There is a fair amount of information on the net about it.

Apply definitely CGAffineTransform* to a UIView

I'm having a problem with scale transformation I have to apply to UIViews on Swift (but it's the same in objective-c too)
I'm applying a CGAffineTransformMakeScale() to multiples views during a gestureRecognizer.
It's like a loop for a cards deck. I remove the one on top and the X others behind scale up and a new one is added in the back.
The first iteration works as expected. But when I try to swipe the new front one, all the cards reset to their initial frame size because i'm trying to apply a new transform, which seems to cancel the previous one and reset the view to its initial state.
How can I apply definitely/commit the first transform change to be able to apply a new one after that based on the UIView resulting new size ?
I tried a UIView.commitAnimations() but no change.
EDIT :
Here's a simple example to understand what I try to do :
Imagine I have an initial UIView of 100x100
I have a shrink factor of 0.95, which means next views behind will be 95x95, then 90.25, then 85.73, etc
If I remove the top one (100x100), I want to scale up the others, so the 95x95 will become 100x100, etc
This is done by applying the inverse of the shrink factor, here 1.052631...
First time I apply the inverse factor, all views are correctly resized.
My problem is, when I trigger again by a swipe on the new front UIView a new resize of all views (So, for example, the 90.25x90.25 which became 95x95 should now scale to 100x100).
At this moment, the same CGAffineTransformMakeScale() is apply to all views, which all instantly reset to their original frame size (so the now 95x95 reset to 90.25x90.25, and then begin to apply the transformation on this old size).
As suggested here or elsewhere, using UIView.commitAnimations() in the end of each transformation don't change anything, and using a CGAffineTransformConcat() is like powering over and over the scaling by himself and of course views become insanely big...
I hope I made myself more clear, that's not easy to explain, don't hesitate to ask if something is wrong here.
After a lot of reading and consulting colleagues who know better than me about iOS programmation, here's my conclusion :
Applying a CGAffineTransformMakeScale() only modify visually a view but not its properties, and since it's difficult (and costly) to modify afterward the bounds and/or frame of a view, I should avoid to try to make a transform, update bounds, make another transform, etc.
Applying the same CGAffineTransformMakeScale() only reset the effect and not apply to the previous one.
Applying a CGAffineTransformScale() with the same values on top of the previous CGAffineTransformMakeScale() (or with a CGAffineTransformConcat()) has some unpredictable effect and will be very difficult to calculate precisely the new values to apply each time to get the effect I want.
The best way I can go with this is only applying one CGAffineTransformMakeScale() that I will keep updating scales values all along the view's life.
It implies now for me to rework all my implementation logic in reverse, but that's the easiest way to do this right.
Thanks all for your tips.

iOS: Segmented touchmap over image

I've been trying to find a way to solve this problem, and haven't been able to find anything useful, so forgive me if this is a duplicate of something I couldn't find.
I have, essentially, a large complicated image in the style of a stained glass window in a scroll view so that I can pan and zoom around it. Each of the individual segments of the window has some information associated with it. What I need to be able to do is tap on any of the segments and determine which segment was tapped so that I can display the information. What I'm not sure of is how to do the mapping between touch points and segments. Most of the segments aren't even regular polygon shapes let alone orthogonal squares, so I can't think of a straightforward way to determine which segment I've tapped.
If anybody has any ideas as to how I might go about implementing this, it would be most appreciated!
Cheers
Put each individual segment in a different layer. Now you can do hit-testing on what layer was tapped. Your test must be designed so that if a layer was tapped but on a transparent area (i.e. outside its segment), your test will fall through to the next layer behind it. Thus the test will succeed if and when you discover a layer's non-transparent region under the tap. Since it is one segment per layer, the segment is the one corresponding to that layer.

Adjust Frame of Overlay without affecting MKMapView beneath it?

I've got an MKMapView and overlay (a curved line) on top of it. I'd like to be able to adjust the overlay's frame to move it across the map and transform its height/width (and thus distort the image) as necessary from user inputs. But here's the trick: I DON'T want to move the map itself, just the shape overlaid on top of it.
I've contemplated just erasing and re-applying the overlay, but the input changes so frequently (it's based on the user's compass direction which is constantly changing ever-so-slightly) that the shape just ends up flickering off and on in a very distracting way. So I feel like I need to adjust the shape as-is, rather than removing it, if I can.
Thing is, when I try to access the overlay to try to transform it, XCode tells me that the self.mapView.overlays array is read-only. I've found questions on Stack Overflow, though, that seem to imply that overlays can be rotated, and thus edited.
Does anyone know how to pull this off? I would provide code, but aside from the simple "add overlay" function in viewDidLoad, I don't have any yet...
When you add an overlay, why don't you keep an external reference to it? Then you can use this property to change its frame (like you saw on the attached questions) without removing and adding que overlay.

How can I reproduce a "box" transition animation in iOS?

I want to build an animated transition between two view controllers in iOS, resembling the "Box" transition in PowerPoint or the "Reflection" transition in Keynote.
You can see it here, at 2:10:
http://youtu.be/1fLQg5hFQQg?t=2m10s
What's the best way to do this?
Thanks!
That would be a complex animation to recreate. You'd need to use a CAAnimationGroup that grouped several different animations running at once. You'd want to animate a rotation around the y axis with the center of rotation lifted off the screen, on both the view controller that is animating away and the view that your are animating into place.
You would have to tweak the transform to make it draw with perspective (you add a small value to the .m34 record in the transform). That's because CA animations are orthographic by default (they don't show perspective.)
The reflections could be created using a special subclass of CALayer that lets you create duplicates of a layer. I'm blanking on the name of that layer subclass at the moment. You'd set up 1 duplicate with a scale of -1 on the y axis to flip it upside down, and a darkening effect. I've never done it myself, but I've seen several examples in books and online.

Resources