How to Rotate a CALayer-backed NSView subclass - cocoa

I have a custom NSView subclass that I want to animate with Core Animation. I am already (without CA) setting the position and rotation of these views with NSView's setFrameOrigin and setFrameRotation methods. However, no matter what I do, once I add a layer backing to the views I can't get them to rotate.
I've tried using NSView's setFrameRotation and setFrameCenterRotation methods. The latter moves the view a bit, but doesn't rotate its content. The former has no effect. Applying a CATransform3D created by CATransform3DRotate to the view's layer also has no effect.
I'm feeling a little dumb asking this question, because it seems like something that should be easy, but for the life of me I can't figure out how to make it work. Someone, please make me smack my forehead at how easy it was. :)

Turns out that the superview needed to be layer-backed as well in order for this to work. Making that change fixed it.

Related

How to animate horizontal bar with right cap, by UIView animation in iPhone

I got wiered but unsurprising animation from call UIView animation, I don't know if it works the same by using CALayer animation. I guess it is.
please see this picture: what I want is to animate a horizontal bar growing horizontally, what I do is:
Subclass a UIView, called UIViewBar, and in its drawRect:rect method, I draw the shape of rectangle and a right cap, it's done by
CGContextMoveToPoint A
CGcontextAddLineToPoint B
CGContextAddArcToPoint D
CGContextAddLineToPoint C
//then close the path and fill the context
Then I call this UIViewBar (initWithFrame:rect) in my UIViewController, and the shape is what I want, looks fine. BUT when I perform [UIView animation] say from original rect to rectGrew it does not perform nicely. Instead, it perform as the picture says.
Well, after thinking, it's not totally unreasonable because when the UIView horizontally stretches itself, it does not know the cap will not be changed. So is there another way to do this?
Actually, I'm very new to drawing, graphic, and animation. What I know is that (if wrong please kindly correct me):
If I want to "draw something", I should override the UIView's drawRect method, and this is done by initing the UIView, should not or better not to be called outside. Say I drew a rectangle in a UIView by CGContextFillRect.....
But what if I want to animate this rectangle? I cannot make animation based on Quartz2D, but from UIView animation or CALayer(deeper tech), so What I have to do is to make the rectangle itself as a seperate UIViewRect seperately, so I can call the [UIViewRect animation] method, AM I RIGHT ON THIS
If so, I have to make every rectangle that I want to animate to be UIView respectively. Doesn't it affect performance? Or it is just the way apple prefers to do ?
Any suggestion will be much helpful, GREAT thanks.
Wow, it's the first time that no answer posted at all! TO answer my question: it requires to consider animate custom property of CALayer. The custom property is the AB width (the width without cap width, that should work). If someone wants detailed code. Please google custom property animate in CALayer.

Combining drawRect: with other UIKit drawing

I'm working on some other person's code, which does most of the UI drawing in drawRect:. However, I need to add some animations (UIActivityIndicator animating, for example) to the view, and since drawRect: appears to be frame based, there doesn't seem to be an easy way.
I understand it is a mistake to fiddle with view hierarchies in drawRect, so I can't simply addSubview:. I want the activity indicator to do its own drawing, after drawRect:, because it should overlap. How should I approach this?

NSWindow Content Border messing with CALayer's geometry

I have an NSWindow with a 32px bottom content border. Inside the window's view, I have two custom subviews. Each of them are layer backed, and I'm tracking the mouse with an NSTrackingArea. Part of what I'm doing is some mouseOver effects with CoreAnimation. This is not a problem in general, but I noticed something kind of strange and wondered if anyone knows why this is happening.
When setting up the trackingArea and mouseOver method, I hitTest the root layer and log the layer's name so I can see if the geometry of the various sublayers hold water when I resize the window. Internally, they seem (and look) fine. Visually, they are in the right place, but when I move the mouse, I notice that the though the mouse is physically over a layer, hitTest is returning whatever layer is 32 px above it. However, if I remove the content border, it works as you would expect and the correct layer is returned.
I obviously need the content border, so I have a very simple workaround which involves offsetting the hitTest point by 32px. This works fine, but it just seems weird that the presence of a content border seems to skewing the co-ordinate system of these subviews. Does anyone know why this could be happening?
NSEvent returns mouse locations relative to the window's coordinate system, not the targeted view's. You probably need to call convertRect:fromView: to get the correct coordinates.

Automatic NSView resizing

I'm doing something with cocoa which I think is a bit complicate for a beginner like me. I tried a few things, but I admit I need some theory first, because I would like to understand exactly the meaning of this concepts.
I see that every NSView and every class that subclasses it has one thing called frame, and one called bounds. They both have a size with width and height and an origin.
I have an NSView with an NSTableView inside of it.
I have the size of a row from the table view, and I would like to set the height of both NSView and NSTableView equal to rows*rowSize, in a way that the group NSView+subviews is automatically resized when an object is added or removed to and from the data source of the Table View.
I made some experiments, but I did end a bit confused about frame, bounds, sizes and so on. I don't know what I should change and how.
Can you please give me an hint about what bounds and frame basically are, and how can I achieve that magic resizing?
Thank you for your replies in advance. Best regards,
—Albé
The difference between frame and bounds is covered very nicely in the View Programming Guide (under View Geometry).
You'll also want to peruse the NSView Class Reference, where you'll find some handy notifications, such as NSViewFrameDidChangeNotification and handy methods such as setPostsFrameChangedNotifications:.

How does CATransition work?

CATransition is quite unusual. Consider the following code.
CATransition* trans=[CATransition animation];
trans.duration=0.5;
trans.type=kCATransitionFade;
[self.holdingView.layer addAnimation:trans forKey:nil];
self.loadingView.hidden=YES;
self.displayView.hidden=NO;
Notice that nowhere did I tell the transition that I wanted to display the displayView rather than loadingView, so the views must somehow access the transition themselves. Can anyone explain in more detail how this works?
When you add the transition as an animation, an implicit CATransaction is begun. From that point on, all modifications to layer properties are going to be animated rather than immediately applied. The way the CATransition performs this animation to to take a snapshot of the view before the layer properties are changed, and a snapshot of what the view will look like after the layer properties are changed. It then uses a filter (on Mac this is Core Image, but on iPhone I'm guessing it's just hard-coded math) to iterate between those two images over time.
This is a key feature of Core Animation. Your draw logic doesn't generally need to deal with the animation. You're given a graphics context, you draw into it, you're done. The system handles compositing that with other images over time (or rotating it in space, or whatever). So in the case of changing the hidden state, the initial-state fully composited image is blended with the final-state composted image. Very fast on a GPU, and it doesn't really matter what change you made to the view.

Resources