This is my problem:
The background of the progress indicator doesn't appear to be redrawing, and it's certainely not transparent. I'm using core animation to animate the image in the background; when I don't use core animation it looks fine. This is the code I am using:
[[NSAnimationContext currentContext] setDuration:0.25];
[[ViewImage animator] setAlphaValue:0.5f ];
[[statusText animator] setAlphaValue:0.1f ];
[progressIndicator usesThreadedAnimation ];
The progress indicator doesn't use core animation. I have also tried removing [progressIndicator usesThreadedAnimation]; which doesn't help.
-usesThreadedAnimation is the getter for the property. You want -setUsesThreadedAnimation: to set the property.
Also, for the transparency issue, I believe you need to switch on layers for at least the progress indicator if not the parent view as well. That should fix the transparency issue.
Related
I'm making a navigation controller class for Mac OS X.
I want to replace the current view with a kCATransitionPush animation.
Like in this post:
Core Animation Tutorial - Wizard Dialog With Transitions
The CATransition is set up like this:
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.view setAnimations:#{ #"subviews" : transition }];
However, when I replace the views, there is a fade animation, which is being automatically added.
[NSAnimationContext beginGrouping];
{
[[self.view animator] replaceSubview:_currentViewController.view with:newViewController.view];
}
[NSAnimationContext endGrouping];
How can I do a push animation without the fading?
The best way I've found to get smooth Core Animation transitions that works regardless of whether the view supports CA or not is to do the following:
Create an image of the view you are trying to animate, using NSView -cacheDisplayInRect:toBitmapImageRep or a similar method
Put that image in an NSImageView
Layer back the image view, which will draw fine without glitches when layer backed
Add the image view as a subview over the view that you are trying to transition
Animate the image view frame using NSView's animator proxy
Remove the image view once the animation has completed
I suspect you're running into implicit animations - Core Animation will automatically animate layer property changes that happen outside of your own transactions.
There's a good summary of several methods for disabling these implicit animations in these two questions:
How to disable CALayer implicit animations?
Disabling implicit animations in -[CALayer setNeedsDisplayInRect:]
...and you can read more about implicit transactions in the Core Animation docs
I think the transition from left transition includes a built-in fade. The IOS push transitions do.
If you don't want that, you might have to roll your own push transition using Core Animation. This would be easy in iOS with UIView animations. Sadly, there is not an equivalent in Mac OS. I wish Apple would go back and add view animations to Mac OS. I get spoiled using them in iOS, and then miss them when I work on Mac applications.
Add below code
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[transition setDuration:0.5];
[self.view.layer addAnimation:transition forKey:kCATransition];
I have a NSTextField as a label, showing a string.
I want to animate this label from right to left, if the content of it is too large to be displayed at once.
I've done this with an NSTimer so far, it works, but it's just not a very good solution.
The labels are displayed in an NSTextFieldCell, in a Table View.
They often get out of sync, and I guess it's just eating up a lot of CPU/GPU resources.
Is there another way with Core Animation to do this?
I have tried it with layers, as you can see right here:
CALayer and drawRect
but I didn't get it working either.
I would really appreciate your help.
You can simply animate the position of NSTextField with animator like
[[textField animator] setFrameOrigin:NSMakePoint(x,y)];
you can also embed it in "CATrancation" code like this:
[CATransaction begin];
[CATransaction setAnimationDuration:0.5];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[[textField animator] setFrameOrigin:NSMakePoint(x,y)];
[CATransaction commit];
if you need animation delegate, you can use CABasicAnimation
CABasicAnimation* animation = [CABasicAnimation animation];
animation.delegate = self;
NSDictionary *animations = [NSDictionary dictionaryWithObjectsAndKeys:animation,#"frameOrigin",nil];
[textField setAnimations:animations];
[[textField animator] setFrameOrigin:NSMakePoint(x,y)];
Delegate methods are
- (void)animationDidStart:(CAAnimation *)theAnimation;
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag;
If you need to mask your text field, just embed it in other NSView.
First, animate the label using one of the functions offered in the other answers.
Then, if you want to display another view on the sides without overlapping, you can:
Insert the label in a subview with the limits you wish
Use bringSubviewtoFront: or sendSubviewToBack: to make sure your label stays in the back
After I overlay an application over my previous application, I go back to previous application and encounter a few errors:
certain components have disappeared
only way to make the components visible is to resize the window
that seems to redraw the whole canvas.
Weird thing is that there are only a couple of components and drawn images that are missing
It doesn't always happen but only a couple of times
I haven't found a solid way to reproduce the problem.
Anybody have an Idea why this is happening?
I experienced exactly the same issue (view was updated correctly only after resizing), except that I've used OpenGL drawing in OSX game.
My problem was solved by adding this:
GLint vblSynch = 1;
[[self openGLContext] setValues:&vblSynch forParameter:NSOpenGLCPSwapInterval];
in my custom NSOpenGLView init method.
Then I've implemented:
- (void)drawRect:(NSRect)rect
{
[self destroyFramebuffer]; // glDeleteFramebuffers..
[self createFramebuffer]; // [super prepareOpenGl], glGenFrame(Render)Buffers, bind buffers, etc
[self drawView]; // [[self openGLContext] makeCurrentContext], make some drawing, [[self openGLContext] flushBuffer]..
}
like this.
After these changes, when window gets focus it redraws itself (without any resizing stuff :) ).
Hope this helps!
I have this code to move a view.
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:#"transform.translation.x"];
theAnimation.duration=1;
theAnimation.repeatCount=1;
theAnimation.autoreverses=NO;
theAnimation.fromValue=[NSNumber numberWithFloat:0];
theAnimation.toValue=[NSNumber numberWithFloat:-60];
[view.layer addAnimation:theAnimation forKey:#"animateLayer"];
The problem is: The actual coordinates of the view get reseted after the animation has finished. Is it possible that the view remains at the new coordinates after the animation has finished?
Thanks.
In addition to attaching an animation that animates the property, you have to actually set the property to its final value. Crazy, isn't it? Try doing this before you add the animation:
[view.layer setValue:[NSNumber numberWithFloat:-60] forKey:#"transform.translation.x"];
I strongly recommend watching the WWDC 2011 video "Core Animation Essentials". It explains this, and covers a lot of useful information for anyone using Core Animation. You can find it here: https://developer.apple.com/videos/wwdc/2011/
I created a custom view to a button, as I need to implement some highlighting when the mouse is over. The class is very simple, and I already implemented mouseEntered: as well as mouseExited:. The view was registered for tracking in the init method (not sure if it's the best place).
The problem is drawing. I keep an ivar mouseOver, set to YES on mouse enter and NO on mouse exited. The other ivar is for the image, called image. The difference between mouse over or not when it comes to drawing, is the transparency. Here is my drawRect::
- (void)drawRect:(NSRect)dirtyRect
{
[image drawAtPoint:NSMakePoint(0.0,0.0)
fromRect:dirtyRect
operation:NSCompositeCopy
fraction:((mouseOver) ? 1.0 : 0.0)];
}
It works nicely, but only when the mouse first entered, apparently. I guess the problem is that the view is not cleared before drawing the other image. I tried adding:
[[NSColor clearColor] set];
NSRectFillUsingOperation(dirtyRect, NSCompositeClear);
But without success. How can I fix this?
[NSColor clearColor] is a purely transparent color. You probably want to fill using a color with some opacity, like, say, [NSColor whiteColor].