Efficient way to handle CATransitions

Discussion in 'iOS Development' started by Axis, Aug 26, 2009.

  1. Axis

    Axis Super Moderator Staff Member

    Joined:
    Dec 2, 2007
    Messages:
    6,288
    Likes Received:
    133
    Device:
    iPhone 4S (White)
    In the name of Object-Oriented Programming, here is a neat little way to handle CATransitions, useful for projects moderately to heavily reliant on them.

    With this class, you can pre-configure any CATransition you'll ever use, and forget about it until you need it.

    EDIT: Thanks to Skylar's input, I've revised things to be a bit more efficient.

    [OBJC]
    // Animator.h

    #import <Foundation/Foundation.h>
    #import <QuartzCore/QuartzCore.h>


    @interface Animator : NSObject {

    }

    + (CATransition *)transitionWithDuration

    Please Register or Log in to view images

    float)duration andType

    Please Register or Log in to view images

    NSString *)type andSubtype

    Please Register or Log in to view images

    NSString *)subtype;

    /*
    * TYPES:
    *
    * kCATransitionFade
    * kCATransitionMoveIn
    * kCATransitionPush
    * kCATransitionReveal
    *
    * SUBTYPES:
    *
    * kCATransitionFromRight
    * kCATransitionFromLeft
    * kCATransitionFromTop
    * kCATransitionFromBottom
    *
    */

    @end
    [/OBJC]

    [OBJC]
    #import "Animator.h"


    @implementation Animator

    + (CATransition *)transitionWithDuration

    Please Register or Log in to view images

    float)duration andType

    Please Register or Log in to view images

    NSString *)type andSubtype

    Please Register or Log in to view images

    NSString *)subtype {

    CATransition *transition = [CATransition animation];
    transition.duration = duration;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = type;
    transition.subtype = subtype;

    return transition;
    }

    @end
    [/OBJC]

    To use this class, #import it into whatever classes of yours will use it. Then, integrate it like this:

    [OBJC]
    // Where 'bubble' inherits from UIView
    [bubble.layer addAnimation:[Animator transitionWithDuration:0.75 andType:kCATransitionPush andSubtype:kCATransitionFromRight] forKey:nil];

    [self.view addSubview:bubble];
    [/OBJC]
  2. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    You're getting there : )

    One thing you might want to do is consider putting these methods into a UIView subclass. Similar to how Apple handles transitions (UITransitionView) and PocketTouch handles transitions (PT/FKTAnimationView).

    Imbedding the animator into a view allows you to track the animation and call/work animation/view delegation. It would also allow for easy compounding of animations.

    Take a look at the .h for my FKAnimationView:
    [OBJC]//
    // FKTransitionView.h
    // CustomTransition-Quartz
    //
    // Created by Skylar Cantu on 7/27/09.
    // Copyright 2009 Skylar Cantu. All rights reserved.
    //

    #import <UIKit/UIKit.h>
    #import <QuartzCore/QuartzCore.h>

    #import "FKColorConverter.h"

    #import "Global.h"


    #define MAX_REPEAT 10000 //animation iterations
    #define kFKDefaultSpeed 2 //seconds

    typedef enum {
    FKRotationTypeFlat,
    FKRotationTypeHorizontal,
    FKRotationTypeVertical,
    FKRotationTypeFlatHorizontal,
    FKRotationTypeFlatVertical,
    FKRotationTypeHorizontalVertical,
    FKRotationTypeAll
    } FKRotationType;

    typedef enum {
    FKRotationModeAuto,
    FKRotationModeAutoReverse,
    FKRotationModeNone
    } FKRotationMode;

    typedef enum {
    FKTransitionTypeFlipFromLeft,
    FKTransitionTypeFlipFromRight,
    FKTransitionTypeCurlUp,
    FKTransitionTypeCurlDown,
    FKTransitionTypeFade,
    FKTransitionTypeMoveIn,
    FKTransitionTypePush,
    FKTransitionTypeReveal,
    FKTransitionTypeRippleEffect,
    FKTransitionTypeRandom
    } FKTransitionType;

    typedef enum {
    FKTransitionSubtypeFromRight,
    FKTransitionSubtypeFromLeft,
    FKTransitionSubtypeFromTop,
    FKTransitionSubtypeFromBottom,
    FKTransitionSubtypeRandom
    } FKTransitionSubtype;


    @protocol FKAnimationViewDelegate;

    @interface FKAnimationView : UIView {
    BOOL showsPath; //Flag MUST be set prior to calling the animation message. Flag will be lowered by animation.
    BOOL isTransitioning;
    id<FKAnimationViewDelegate> delegate;
    }

    @property (nonatomic) BOOL showsPath;
    @property (nonatomic, readonly) BOOL isTransitioning;
    @property (nonatomic, assign) id<FKAnimationViewDelegate> delegate;

    - (void)scaleByX

    Please Register or Log in to view images

    float)x Y

    Please Register or Log in to view images

    float)y Z

    Please Register or Log in to view images

    float)z;
    - (void)scaleLayer

    Please Register or Log in to view images

    CALayer *)layer byX

    Please Register or Log in to view images

    float)x Y

    Please Register or Log in to view images

    float)y Z

    Please Register or Log in to view images

    float)z;
    - (void)scaleLayer

    Please Register or Log in to view images

    CALayer *)layer byX

    Please Register or Log in to view images

    float)x Y

    Please Register or Log in to view images

    float)y Z

    Please Register or Log in to view images

    float)z withSpeed

    Please Register or Log in to view images

    float)seconds;

    - (void)spinWithDuration

    Please Register or Log in to view images

    float)seconds; //Duration of semispin, not total animation duration
    - (void)spinWithType

    Please Register or Log in to view images

    FKRotationType)type forDuration

    Please Register or Log in to view images

    float)seconds;

    - (void)moveAlongPath

    Please Register or Log in to view images

    CGPathRef)path;
    - (void)moveAlongPath

    Please Register or Log in to view images

    CGPathRef)path withSpeed

    Please Register or Log in to view images

    float) seconds;
    - (void)moveSubview

    Please Register or Log in to view images

    UIView *)subview alongPath

    Please Register or Log in to view images

    CGPathRef)path;
    - (void)moveSubview

    Please Register or Log in to view images

    UIView *)subview alongPath

    Please Register or Log in to view images

    CGPathRef)path withSpeed

    Please Register or Log in to view images

    float)seconds;
    - (void)moveSubview

    Please Register or Log in to view images

    UIView *)subview alongPath

    Please Register or Log in to view images

    CGPathRef)path withSpeed

    Please Register or Log in to view images

    float)seconds andRotationMode

    Please Register or Log in to view images

    FKRotationMode)rotationMode;

    - (void)performTransitionType

    Please Register or Log in to view images

    FKTransitionType)type andSubtype

    Please Register or Log in to view images

    FKTransitionSubtype)subtype;
    - (void)transition

    Please Register or Log in to view images

    FKTransitionType)type

    Please Register or Log in to view images

    FKTransitionSubtype)subtype toView

    Please Register or Log in to view images

    UIView *)toView;
    - (void)pushView

    Please Register or Log in to view images

    UIView *)view withTransitionType

    Please Register or Log in to view images

    FKTransitionType)type andSubtype

    Please Register or Log in to view images

    FKTransitionSubtype)subtype;
    - (void)popViewWithTransitionType

    Please Register or Log in to view images

    FKTransitionType)type andSubtype

    Please Register or Log in to view images

    FKTransitionSubtype)subtype;

    @end


    @protocol FKAnimationViewDelegate <NSObject>

    @optional
    - (void)transitionWillBegin; //Called only on Transitions
    - (void)transitionDidStop

    Please Register or Log in to view images

    BOOL)finished; //Called only on Transitions

    @end[/OBJC]


    .Mov 1: http://www.skylarcantu.com/videos/CAAnimations/CAAnimations.mov
    .Mov 2: http://www.skylarcantu.com/videos/CAAnimations/CAAnimations2.mov
    .Mov 3: http://www.skylarcantu.com/videos/CAAnimations/CAAnimations3.mov
    .Mov 4: http://www.skylarcantu.com/videos/CAAnimations/CAAnimations4.mov

    Again, have at this, and have a blast! Working with Quartz is a ton of fun!
  3. cocotutch

    cocotutch Community Development Team Staff Member

    Joined:
    Oct 6, 2008
    Messages:
    1,285
    Likes Received:
    117
    Device:
    5G iPod touch
    Hey Skylar, in your TEST_MEDIACONTROL_APP sample available somewhere here, you use a Twist animation on the Album Art, how did you get that working on 3.0, also the Ripple Effect, and can I use it in the App Store or is it a Private API that Apple hate you using?

    TY,

    coco
  4. Axis

    Axis Super Moderator Staff Member

    Joined:
    Dec 2, 2007
    Messages:
    6,288
    Likes Received:
    133
    Device:
    iPhone 4S (White)
    Skylar, that's a brilliant idea. Thanks.
  5. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    In 3.0, the twist, etc, have been moved to UIKit. You will need to access the animations from there.
  6. cocotutch

    cocotutch Community Development Team Staff Member

    Joined:
    Oct 6, 2008
    Messages:
    1,285
    Likes Received:
    117
    Device:
    5G iPod touch
    How do I call them from there? UIView animation? No experience in this field, but I figured out CATransitions in general recently.........

    Please Register or Log in to view images

    And Apple don't hate them on the store do they?
  7. gojohnnyboi

    gojohnnyboi Well-Known Member

    Joined:
    Jan 25, 2008
    Messages:
    3,339
    Likes Received:
    55
    @SkylarEC: Ah, that's a neat idea. (Remembers UITransitionView)
  8. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    That's exactly it. I noticed that Apple still uses UITransitionView (in UINavigationControllers, for example); which I had toyed with it for a bit (see this thread) several months ago before moving on to other areas.

    Later, when I began porting PocketTouch to 3.0 and I had decided to use only public objects, I realized that I needed to implement my own transition view. And so, PTTransitionView was born. And just a few months after that, once I finished PocketTouch, I decided to expand PTTransitionView into PTAnimationView (R.I.P PTTransitionView). Seeing how that came out, I removed PTTransitionView from PocketTouch adn replaced it with PTAnimationView.

    When I release the upgraded PocketTouch framework, hence known as FailKit, the view will be known as FKAnimationView.
  9. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    Re your edit to the first post. You still run into the problem of having to include the "Animator" in every view that you want it. Also, setting the delegate to self is still useless, as your "class" never exists. I don't know if the result would be a crash in your app, or the equivalent of setting the delegate to nil.

    Also, your method name goes against Objective-C naming conventions:
    + (CATransition *)makeTransitionWith:etc:

    Make transition implies that it will be returning an animation. Your method states that it is returning a transition, so wtf is an "animation?" Your method name should be along the lines of
    + (CATransition *)transitionWith:stuff
  10. Axis

    Axis Super Moderator Staff Member

    Joined:
    Dec 2, 2007
    Messages:
    6,288
    Likes Received:
    133
    Device:
    iPhone 4S (White)
    I don't know what I was thinking (or lack thereof) with the delegate.

    Please Register or Log in to view images



    Your first in this thread inspired me to figure a few things out, but I haven't had the time yet. This "tutorial" shouldn't be a work in progress, I assume. What I considered to be a simple but relatively sound solution was immediately surpassed the functionality of what you posted (which is good). I'm not going to replicate your class, but I hope to implement some of its aspects soon.

    Peace.

Share This Page