Re: layer contents briefly appearing stretched when resizing
Re: layer contents briefly appearing stretched when resizing
- Subject: Re: layer contents briefly appearing stretched when resizing
- From: Roland King <email@hidden>
- Date: Thu, 3 Feb 2011 09:10:16 +0800
thanks Matt, I did see your message and I did try layoutSublayersOfLayer: (I assume that works because the UIView is automatically the CALayer's delegate) and I still have the problem. However I agree your simple example is the equivalent of what I'm doing, and I just compiled a version of it, and it works and it doesn't flash. QED, despite having torn my code apart numerous times, I must still be missing something.
Thanks for the example showing that it should work, I will now return to my code and hunt harder to find what I've messed up here.
On 03-Feb-2011, at 4:32 AM, Matt Neuburg wrote:
> I really think you ought to try what I said. I just did and I'm not seeing any flash. Here's my code:
>
>
> - (IBAction) doButton: (id) sender { // toggle view size
> CGRect f = self->mmview.frame;
> if (f.size.height == 200) {
> f.size.height = f.size.width = 100;
> self->mmview.frame = f;
> return;
> }
> if (f.size.height == 100) {
> f.size.height = f.size.width = 200;
> self->mmview.frame = f;
> return;
> }
> }
>
> And here's the code for the view subclass:
>
> - (void) awakeFromNib {
> [super awakeFromNib];
> CALayer* lay = [CALayer layer];
> lay.frame = self.layer.bounds;
> [self.layer addSublayer: lay];
> lay.contents = (id)[[UIImage imageNamed:@"manny.jpg"] CGImage];
> self.which = @"manny";
> }
>
> - (void) layoutSublayersOfLayer: (CALayer*) layer {
> [CATransaction setDisableActions:YES]; // looks fine without this, too
> for (CALayer* lay in layer.sublayers) {
> lay.frame = layer.bounds;
> if (lay.contents) {
> if ([self.which isEqualToString:@"manny"]) {
> lay.contents = (id)[[UIImage imageNamed:@"moe.jpg"] CGImage];
> self.which = @"moe";
> }
> else if ([self.which isEqualToString:@"moe"]) {
> lay.contents = (id)[[UIImage imageNamed:@"manny.jpg"] CGImage];
> self.which = @"manny";
> }
> }
> }
> }
>
> So it seems to me I'm doing exactly what you said; when the view changes frame, I'm changing the sublayer frame to match, plus I'm changing the sublayer contents. And there's no flash.
>
> m.
>
> On Wed, 2 Feb 2011 18:29:48 +0800, Roland King <email@hidden> said:
>>
>> On 02-Feb-2011, at 1:38 AM, David Duncan wrote:
>>
>>> On Feb 1, 2011, at 4:32 AM, Roland King wrote:
>>>
>>>> I have a UIView subclass in my iOS app and the content for that UIView is 3 CALayers, each with a bitmap image for their content, added as sublayers of the UIView's layer. Each of the CALayers is the full size of the UIView's layer (they have transparency to composite them together).
>>>>
>>>> When the UIView is resized the setFrame: method is called and I have a custom implementation of that which sets the bounds of the sublayers so they again fill the UIView's layer, and draws a new bitmap for each of them of the right size and sets it into their contents.
>>>>
>>>> However, when I resize, there's a brief flash of the current content, before it's been redrawn, stretched to fill the new sized window, before the new content replaces it. Nothing I've tried has been able to stop that brief flash and I can't figure out where it's coming from.
>>>
>>>
>>> I suppose my first question is why not just use UIViews instead? They should already abstract all of what you need to make this work away from you, and you should only need to set the view's contentMode property to UIViewContentModeRedraw to get the behavior you seem to desire. Then it would just be a matter of teaching the UIViews how to draw themselves to generate their own content instead of having the parent UIView do so and push it to them.
>>>
>>> As for overall, I'm not entirely certain what is happening, but it sounds like you have a timing issue, possibly one where the view's are resized on one runloop invocation and their contents replaced on the next. Instead of overriding -setFrame: you should override -layoutSubViews: which should catch more cases where layout is needed and allow you to do the work you need at the right time.
>>> --
>>> David Duncan
>>>
>>
>> Yeah I ended up with layers because I started constructing one UIImage by drawing to a bitmap context and then split it up into three pieces (backdrop, bit in the middle and an overlay) so I didn't have to keep redrawing the bits that weren't changing and at that point I though layers instead of images, but I certainly try to pull myself up the tree a bit and move it back to UIViews. I'm just bothered that I can't figure this out, CALayers should work ok for this.
>>
>> -layoutSubViews: doesn't work for this either, I tried that already, and that does seem to ensure I end up with the calls on two different runloop invocations, which is worse.
>>
>> I tend to agree that it's a timing issue, but I can't find it, I'm explicitly doing everything in the one method, removing layers or removing their contents before they are resized etc, so the only thought I'm left with is that core animation is shifting the actual work to another thread, even when I've turned off actions and put things in CATransactions and whatever order I do things in makes little difference, that thread sees the net change and animates between it, doing the resize first.
>>
>> Thanks for the reply though, if I can't sort this out (and I have perhaps one more good idea) I'll try using UIImageViews instead.
>>
>>
>>
>>
>
> --
> matt neuburg, phd = email@hidden, <http://www.apeth.net/matt/>
> A fool + a tool + an autorelease pool = cool!
> AppleScript: the Definitive Guide - Second Edition!
> http://www.apeth.net/matt/default.html#applescriptthings
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden