views:

275

answers:

3

Hello

I have some basic code for adding a QTMovieView. I want it to fade in, so I add an animation on setAlphaValue. Only issue is that it doesn't work. The alpha value is instantly set to whatever it was supposed to animate to. If I try animating e.g. setFrame: it works fine. You'll find my code below. This is on 10.5.7 with the Mac OS X 10.5 SDK.

    - (void)addMovie:(NSString *)aFile
    {
            QTMovieView     *aMovieView;
            QTMovie         *aMovie;
            NSRect          contentFrame;

            contentFrame = [[self contentView] frame];

            aMovieView = [[QTMovieView alloc]
                            initWithFrame:contentFrame];
            [aMovieView setWantsLayer:YES];
            [aMovieView setControllerVisible:NO];
            [aMovieView setPreservesAspectRatio:YES];

            aMovie = [[QTMovie alloc]
                            initWithFile:aFile error:nil];

            [aMovieView setMovie:aMovie];

            [aMovieView setAlphaValue:0.4];

            [[self contentView] addSubview:aMovieView];

            [NSAnimationContext beginGrouping];
            [[NSAnimationContext currentContext] setDuration:2.0];
            [[aMovieView animator] setAlphaValue:0.9];
            [NSAnimationContext endGrouping];

    }

Any ideas?

+3  A: 

I don't know for sure but it sounds like QTMovieView may not support alpha compositing. One further test I would try would be to call setWantsLayer on the superview of the QTMovieView to see if that affects the QTMovieViews ability to composite correctly. Probably will not work.

You could try using QTMovieLayer instead. One way to incorporate QTMovieLayer would be to make your own NSView subclass that created and managed a QTMovieLayer that was added inside its root layer. Be aware though that when mixing layer backed views with non layer backed views in the same window you may get funny ordering if the layer backed views are not all in front or are behind and overlapping.

Jon Steinmetz
Thanks for your feedback. The weird thing is, I can e.g. do [movieView setAlphaValue:0.5] and it will be correct. So, my next approach will be to manually fire off a new thread, which would call a method that would tail recurse until alphaValue == 1.0. But it seems stupid, when there's something like Core Animation.Will try the thread approach and come back tomorrow.
Harry Vangberg
That is interesting, so then it would appear it does support alpha. Here are some other things to try.Try making a subclass of QTMovieView and override setAlphaValue:, then use NSLog to log the value being set and see if it is getting set with values multiple times that look like the animation values.Instead of running your own thread try using [NSAnimation][1], it might save you some effort. [1]:http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ApplicationKit/Classes/NSAnimation_Class/Reference/Reference.html
Jon Steinmetz
Changing aspects of the UI from a thread is not a good idea. You're supposed to only do that from the main thread. (Thought experiment: What if the user causes you to fade out the movie view twice at the same time?) I second the animate-the-superview and QTMovieLayer suggestions.
Peter Hosey
Here is another question. Where is addMovie: getting called from? It is possible that the animation won't work too early in the view construction process. If you are only calling this during the setup of your views such as right after loading from a NIB you could try deferring starting the animation, such as using performSelector:withObject:afterDelay:.
Jon Steinmetz
Peter, I see your point with regards to threads.Jon, this is called every time I select a thumbnail in a collection view otherwhere, so that shouldn't be an issue. Also, as I mentioned, animating setKeyFrame: works fine.I will see if I can figure out QTMovieLayer.
Harry Vangberg
A: 

I began on QTMovieLayer, but being less powerfull (of course) than QTMovieView it opened another box of issues. The solution was to use NSAnimation on the QTMovieView. I have a NSAnimation class looking somewhat like this:

AlphaAnimation.h

    #import <Cocoa/Cocoa.h>

    NSString * const AAFadeIn;
    NSString * const AAFadeOut;

    @interface AlphaAnimation : NSAnimation {
            NSView          *animatedObject;
            NSString        *effect;
    }
    - (id)initWithDuration:(NSTimeInterval)duration effect:(NSString *)effect object:(NSView *)object;
    @end

AlphaAnimation.m

    #import "AlphaAnimation.h"

    NSString * const AAFadeIn = @"AAFadeIn";
    NSString * const AAFadeOut = @"AAFadeOut";

    @implementation AlphaAnimation
    - (id)initWithDuration:(NSTimeInterval)aDuration effect:(NSString *)anEffect object:(NSView *)anObject
    {
            self = [super initWithDuration:aDuration animationCurve:0];

            if (self) {
                    animatedObject = anObject;
                    effect = anEffect;
            }

            return self;
    }

    - (void)setCurrentProgress:(NSAnimationProgress)progress
    {
            if ([effect isEqual:AAFadeIn])
                    [animatedObject setAlphaValue:progress];
            else
                    [animatedObject setAlphaValue:1 - progress];
    }
    @end

Which can then be used like this:

animation = [[AlphaAnimation alloc] initWithDuration:0.5 effect:AAFadeIn object:movieView];

[animation setAnimationBlockingMode:NSAnimationNonblocking];
[animation startAnimation];

If your QTMovieViews are in full screen it isn't very smooth, though.

Harry Vangberg
+1  A: 

I suggest NSViewAnimation. It's a subclass of NSAnimation that will do the fading in and out for you.

Peter Hosey
I removed this as an answer, because NSViewAnimation doesn't work with QTMovieView, see: http://lists.apple.com/archives/cocoa-dev/2005/Sep/msg01475.html
Harry Vangberg