CALayer doesn't resize immediately

  • Hi,

    I've been experiencing some problems with Core Animation when resizing
    a view containing CALayers. I've made a simple project that shows the
    issue.

    http://pacificturtle.free.fr/CoreAnimation.zip

    Or here is the code:

    - (id)initWithFrame:(NSRect)frame {
        self = [super initWithFrame:frame];
        if (self) {
      rootLayer = [CALayer layer];
      rootLayer.backgroundColor = [CAView color:C_BLACK];
      rootLayer.layoutManager = [CAConstraintLayoutManager layoutManager];

      CALayer *sublayer = [CALayer layer];
      sublayer.backgroundColor = [CAView color:C_GRAY];
      [sublayer addConstraint:[CAConstraint
    constraintWithAttribute:kCAConstraintMinX

    relativeTo:@"superlayer"

    attribute:kCAConstraintMinX]];

      [sublayer addConstraint:[CAConstraint
    constraintWithAttribute:kCAConstraintWidth

    relativeTo:@"superlayer"

    attribute:kCAConstraintWidth]];

      [sublayer addConstraint:[CAConstraint
    constraintWithAttribute:kCAConstraintMidY

    relativeTo:@"superlayer"

    attribute:kCAConstraintMidY]];

      [sublayer addConstraint:[CAConstraint
    constraintWithAttribute:kCAConstraintHeight

    relativeTo:@"superlayer"

    attribute:kCAConstraintHeight]];

      [rootLayer addSublayer:sublayer];
    }
    return self;
    }

    The rootLayer is filled with black and its sublayer is filled with
    gray. This sublayer should resize itself to fill the rootLayer but
    when I resize the window, it takes some time for the gray layer to
    resize. Is this a bug or am I doing anything wrong ?

    I am using a Powerbook G4 with a retail Leopard version.

    Thanks

    Axel
  • Hi,

    my first guess:

    Instead of configuring the constraints like this

    > [sublayer addConstraint:[CAConstraint
    > constraintWithAttribute:kCAConstraintMinX
    >
    > relativeTo:@"superlayer"
    >
    > attribute:kCAConstraintMinX]];
    >
    > [sublayer addConstraint:[CAConstraint
    > constraintWithAttribute:kCAConstraintWidth
    >
    > relativeTo:@"superlayer"
    >
    > attribute:kCAConstraintWidth]];
    >
    > [sublayer addConstraint:[CAConstraint
    > constraintWithAttribute:kCAConstraintMidY
    >
    > relativeTo:@"superlayer"
    >
    > attribute:kCAConstraintMidY]];
    >
    > [sublayer addConstraint:[CAConstraint
    > constraintWithAttribute:kCAConstraintHeight
    >
    > relativeTo:@"superlayer"
    >
    > attribute:kCAConstraintHeight]];

    it should be sufficient to write

    > [sublayer addConstraint:[CAConstraint
    > constraintWithAttribute:kCAConstraintWidth
    >
    > relativeTo:@"superlayer"
    >
    > attribute:kCAConstraintWidth]];
    >
    > [sublayer addConstraint:[CAConstraint
    > constraintWithAttribute:kCAConstraintHeight
    >
    > relativeTo:@"superlayer"
    >
    > attribute:kCAConstraintHeight]];}

    , i.e., just constraining the width and height in relation to the
    superlayer.

    However, a more elegant solution should be to simply write:

    sublayer.autoresizingMask = kCALayerWidthSizable |
    kCALayerHeightSizable;
    sublayer.layoutManager = [CAConstraintLayoutManager layoutManager];

    All this without actually testing it.

    Thomas S.

    --
    Oldenburg University - Department of Computer Science
    Media Informatics and Multimedia-Systems
    Phone: +49 441 9722-175  -  Fax: +49 441 9722-102
    Escherweg 2  -  D-26121 Oldenburg
  • Hi again,

    Using autoresizingMaks works far better. But after some hours of work,
    I came with the conclusion that CAConstraintLayoutManager performances
    are not what I expect them to be. Even with the Core Animation
    provided - CovertFlow - example, I clearly see the layers translate
    when I resize the view.
    The problem is that I really need to use CAConstrainLayoutManagers,as
    my application does more than the project I included in the first mail.

    Maybe some of you could confirm this issue, it might be a PPC-only
    issue. I hope there is a fix in 10.5.1 if this is a bug...

    Axel

    Le 7 nov. 07 à 11:08, Thomas Schlömer a écrit :

    > Hi,
    >
    > my first guess:
    >
    > Instead of configuring the constraints like this
    >
    >> [sublayer addConstraint:[CAConstraint
    >> constraintWithAttribute:kCAConstraintMinX
    >>
    >> relativeTo:@"superlayer"
    >>
    >> attribute:kCAConstraintMinX]];
    >>
    >> [sublayer addConstraint:[CAConstraint
    >> constraintWithAttribute:kCAConstraintWidth
    >>
    >> relativeTo:@"superlayer"
    >>
    >> attribute:kCAConstraintWidth]];
    >>
    >> [sublayer addConstraint:[CAConstraint
    >> constraintWithAttribute:kCAConstraintMidY
    >>
    >> relativeTo:@"superlayer"
    >>
    >> attribute:kCAConstraintMidY]];
    >>
    >> [sublayer addConstraint:[CAConstraint
    >> constraintWithAttribute:kCAConstraintHeight
    >>
    >> relativeTo:@"superlayer"
    >>
    >> attribute:kCAConstraintHeight]];
    >
    >
    > it should be sufficient to write
    >
    >> [sublayer addConstraint:[CAConstraint
    >> constraintWithAttribute:kCAConstraintWidth
    >>
    >> relativeTo:@"superlayer"
    >>
    >> attribute:kCAConstraintWidth]];
    >>
    >> [sublayer addConstraint:[CAConstraint
    >> constraintWithAttribute:kCAConstraintHeight
    >>
    >> relativeTo:@"superlayer"
    >>
    >> attribute:kCAConstraintHeight]];}
    >
    >
    > , i.e., just constraining the width and height in relation to the
    > superlayer.
    >
    > However, a more elegant solution should be to simply write:
    >
    > sublayer.autoresizingMask = kCALayerWidthSizable |
    > kCALayerHeightSizable;
    > sublayer.layoutManager = [CAConstraintLayoutManager layoutManager];
    >
    >
    > All this without actually testing it.
    >
    > Thomas S.
    >
    > --
    > Oldenburg University - Department of Computer Science
    > Media Informatics and Multimedia-Systems
    > Phone: +49 441 9722-175  -  Fax: +49 441 9722-102
    > Escherweg 2  -  D-26121 Oldenburg
    >
  • adding the list.

    2007/11/8, Bertrand Landry-Hetu <bertrandl...>:
    > I don't think it is a question of performance. I think it's that
    > sometimes we change a property on a layer and expect it to be instant,
    > but instead it is being animated.
    >
    > So far I have found 2 ways of removing animations.
    >
    > If you have changed the property directly, you can call [myLayer
    > removeAllAnimations] which forces the layer to go directly to the
    > final value. That won't work in your case since its the layout manager
    > that changes the sizes and position for you.
    >
    > The other way I found is to disable the default animation for that property:
    >
    > NSDictionary * disabledAnimation = [NSDictionary
    > dictionaryWithObjectsAndKeys: [NSNull null], @"bounds", [NSNull null],
    > @"position", nil];
    >
    > myLayer.actions = disabledAnimation;
    >
    >
    > 2007/11/7, Axel Péju <pejuaxel...>:
    >> Hi again,
    >>
    >> Using autoresizingMaks works far better. But after some hours of work,
    >> I came with the conclusion that CAConstraintLayoutManager performances
    >> are not what I expect them to be. Even with the Core Animation
    >> provided - CovertFlow - example, I clearly see the layers translate
    >> when I resize the view.
    >> The problem is that I really need to use CAConstrainLayoutManagers,as
    >> my application does more than the project I included in the first mail.
    >>
    >> Maybe some of you could confirm this issue, it might be a PPC-only
    >> issue. I hope there is a fix in 10.5.1 if this is a bug...
    >>
    >> Axel
    >>
    >> Le 7 nov. 07 à 11:08, Thomas Schlömer a écrit :
    >>
    >>> Hi,
    >>>
    >>> my first guess:
    >>>
    >>> Instead of configuring the constraints like this
    >>>
    >>>> [sublayer addConstraint:[CAConstraint
    >>>> constraintWithAttribute:kCAConstraintMinX
    >>>>
    >>>> relativeTo:@"superlayer"
    >>>>
    >>>> attribute:kCAConstraintMinX]];
    >>>>
    >>>> [sublayer addConstraint:[CAConstraint
    >>>> constraintWithAttribute:kCAConstraintWidth
    >>>>
    >>>> relativeTo:@"superlayer"
    >>>>
    >>>> attribute:kCAConstraintWidth]];
    >>>>
    >>>> [sublayer addConstraint:[CAConstraint
    >>>> constraintWithAttribute:kCAConstraintMidY
    >>>>
    >>>> relativeTo:@"superlayer"
    >>>>
    >>>> attribute:kCAConstraintMidY]];
    >>>>
    >>>> [sublayer addConstraint:[CAConstraint
    >>>> constraintWithAttribute:kCAConstraintHeight
    >>>>
    >>>> relativeTo:@"superlayer"
    >>>>
    >>>> attribute:kCAConstraintHeight]];
    >>>
    >>>
    >>> it should be sufficient to write
    >>>
    >>>> [sublayer addConstraint:[CAConstraint
    >>>> constraintWithAttribute:kCAConstraintWidth
    >>>>
    >>>> relativeTo:@"superlayer"
    >>>>
    >>>> attribute:kCAConstraintWidth]];
    >>>>
    >>>> [sublayer addConstraint:[CAConstraint
    >>>> constraintWithAttribute:kCAConstraintHeight
    >>>>
    >>>> relativeTo:@"superlayer"
    >>>>
    >>>> attribute:kCAConstraintHeight]];}
    >>>
    >>>
    >>> , i.e., just constraining the width and height in relation to the
    >>> superlayer.
    >>>
    >>> However, a more elegant solution should be to simply write:
    >>>
    >>> sublayer.autoresizingMask = kCALayerWidthSizable |
    >>> kCALayerHeightSizable;
    >>> sublayer.layoutManager = [CAConstraintLayoutManager layoutManager];
    >>>
    >>>
    >>> All this without actually testing it.
    >>>
    >>> Thomas S.
    >>>
    >>> --
    >>> Oldenburg University - Department of Computer Science
    >>> Media Informatics and Multimedia-Systems
    >>> Phone: +49 441 9722-175  -  Fax: +49 441 9722-102
    >>> Escherweg 2  -  D-26121 Oldenburg
    >>>

    >>
    >
  • On Nov 8, 2007, at 6:42 AM, Bertrand Landry-Hetu wrote:

    >> The other way I found is to disable the default animation for that
    >> property:
    >>
    >> NSDictionary * disabledAnimation = [NSDictionary
    >> dictionaryWithObjectsAndKeys: [NSNull null], @"bounds", [NSNull
    >> null],
    >> @"position", nil];
    >>
    >> myLayer.actions = disabledAnimation;
    >

    You can also just disable the actions for that transaction

    http://developer.apple.com/documentation/Cocoa/Conceptual/CoreAnimation_gui
    de/Articles/Transactions.html#/

    /apple_ref/doc/uid/TP40006096-DontLinkElementID_56

    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue
    forKey:kCATransactionDisableActions];
    [aLayer removeFromSuperlayer];
    [CATransaction commit];

    (that maybe should be under implicit animations rather than explicit..
    I'll ave to think about that)
  • oh, and for this particular technique.

    [theLayer.actions setObject:[NSNull null] forKey:@"sublayers"];
    discussed here

    http://developer.apple.com/documentation/Cocoa/Conceptual/CoreAnimation_gui
    de/Articles/Actions.html#/

    /apple_ref/doc/uid/TP40006095

    in the doc.

    On Nov 8, 2007, at 6:42 AM, Bertrand Landry-Hetu wrote:

    >> The other way I found is to disable the default animation for that
    >> property:
    >>
    >> NSDictionary * disabledAnimation = [NSDictionary
    >> dictionaryWithObjectsAndKeys: [NSNull null], @"bounds", [NSNull
    >> null],
    >> @"position", nil];
    >>
    >
  • 2007/11/8, Scott Anguish <scott...>:
    >
    > On Nov 8, 2007, at 6:42 AM, Bertrand Landry-Hetu wrote:
    >
    >>> The other way I found is to disable the default animation for that
    >>> property:
    >>>
    >>> NSDictionary * disabledAnimation = [NSDictionary
    >>> dictionaryWithObjectsAndKeys: [NSNull null], @"bounds", [NSNull
    >>> null],
    >>> @"position", nil];
    >>>
    >>> myLayer.actions = disabledAnimation;
    >>
    >
    >
    > You can also just disable the actions for that transaction
    >
    > http://developer.apple.com/documentation/Cocoa/Conceptual/CoreAnimation_gui
    de/Articles/Transactions.html#/

    > /apple_ref/doc/uid/TP40006096-DontLinkElementID_56
    >
    > [CATransaction begin];
    > [CATransaction setValue:(id)kCFBooleanTrue
    > forKey:kCATransactionDisableActions];
    > [aLayer removeFromSuperlayer];
    > [CATransaction commit];
    >
    >
    > (that maybe should be under implicit animations rather than explicit..
    > I'll ave to think about that)

    Is that supposed to work from within a [CALayoutManager
    layoutSublayersOfLayer:] callback? I usually get a crash when
    commiting inside it, so I assumed I wasn't supposed to do so. I guess
    I should have investigated further.
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today