Thanks for the lengthy explanation, Luke. I was aware of most of this. It seems 
like the result I'm seeing is a consequence of a number of things. Since the 
end result is correct, it seems like it should be possible to do things the way 
I was attempting to do them, but that subtleties in the implementation prevent 
it from behaving correctly.

I tried adjusting the content inset bottom instead, as you suggested, but 
unfortunately this required me to also move the text entry UI separately.

Then I tried just moving the entire container (table view plus message 
composition area) up, and adjusting the contentInset.top appropriately. This 
works correctly.

While it's a pity I can't just do the natural resize-frame-and-adjust-offset, I 
appreciate you giving me a workaround that gives me the results I need.

-- 
Rick


On Apr 17, 2012, at 10:48 , Luke Hiesterman wrote:

> So, attempting to modify both the frame and the contentOffset in the same 
> animation is a problem. This has to do with how UIView animations work 
> coupled with how UIScrollView works. I'm going to give a lengthy explanation 
> of why this doesn't work, but you can skip to the bottom for what should be 
> the solution. 
> 
> First a quick note on how UIView animations work (to make sure we're on the 
> same page):
> 
> 1. When an animatable property is modified within an animation block, UIKit 
> sets up an animation on the given view's underlying CALayer object. That 
> animation has a fromValue and a toValue which define what we're animating 
> from and to. When you set a property, the value you set gets taken as the 
> animation's toValue, and whatever was already there gets set as the 
> fromValue. Thus, if you have a view whose alpha is 0.0, and you set its alpha 
> to 1.0 in an animation block, UIKit sets an alpha animation on the CALayer 
> whose fromValue is 0.0 and whose toValue is 1.0. An interesting caveat here 
> is that if you set the same property twice in the same turn of the runloop, 
> the animation results might not be as you expect, because the fromValue used 
> by UIKit is always the model value just before you make the change. Thus if 
> we start with a view whose alpha is 0.0 and run this code
> 
> [UIView animateWithDuration:0.3 animations:^(void) {
> view.alpha = 1.0;
> ....
> view.alpha = 0.9;
> }];
> 
> The result will be that the view jumps immediately to alpha 1.0, and then 
> animates to 0.9, even though the 1.0 was in the animation block. The second 
> animation clobbers the first one and uses the model value set by the first 
> animation as its fromValue.
> 
> Moving on....
> 
> 2. Frame changes are interesting because a frame is not directly a property 
> of a view - it is a derived property of its center, bounds, and transform. 
> When you modify a view's frame, you are actually modifying its center and 
> bounds, which are each distinctly animatable properties, and UIKit sets up 
> animations on the underlying CALayer for each of them.
> 
> And we also need to make sure we're on the same page about how scrolling 
> works in UIScrollView:
> 
> 3. The portion of any view that is drawn on screen is defined by its bounds - 
> the coordinate space of that view. Normally, a view has a bounds.origin of 
> 0,0 and a bounds.size equal to its frame.size. A UIScrollView brings new 
> content onto the screen, getting  the effect of scrolling, but modifying its 
> bounds.origin. In fact, contentOffset is really just bounds.origin. 
> 
> Ok, so bringing this all together....
> 
> When you change a table view's contentOffset and its frame.size in the same 
> animation, you've actually clobbered one of your animations, because both of 
> those properties ultimately result in a bounds animation on the underlying 
> layer. One is modifying the bounds origin, and the other bounds size, but 
> they're both just bounds animations, and just as we saw in the alpha case 
> above, the second one will stomp on the first one and use the first one as 
> its fromValue. Thus you will see things "jump" to the first bounds value you 
> set and then animate to the second.
> 
> And now what should be a solution to the long-winded explanation of the 
> problem:
> 
> Instead of changing the frame of a table view to accommodate the keyboard 
> coming up, we recommend changing the contentInset. By adding the height of 
> the keyboard to the table's contentInset.bottom, you get additional scrolling 
> area so things don't get stuck behind the keyboard, but you won't be creating 
> a bounds animation in the process. In fact, UITableViewController does this 
> automatically for table views that it manages.
> 
> Hope that helps.
> 
> Luke
> 
> On Apr 16, 2012, at 6:27 PM, Rick Mann wrote:
> 
>> Er, for reference, the view hierarchy is this:
>> 
>> http://latencyzero.com/stuff/ViewHierarchy.png
>> 
>> 
>> On Apr 16, 2012, at 18:16 , Rick Mann wrote:
>> 
>>> 
>>> On Apr 16, 2012, at 16:32 , Luke Hiesterman wrote:
>>> 
>>>> You can do this by wrapping the operation in your own animation block. 
>>>> This simple code demonstrates doing it on 44 point high rows:
>>>> 
>>>>   [UIView animateWithDuration:0.3 animations:^(void) {
>>>>       [tableView beginUpdates];
>>>>       CGPoint contentOffset = tableView.contentOffset;
>>>>       if (contentOffset.y > 0) {
>>>>           contentOffset.y += 44;
>>>>           tableView.contentOffset = contentOffset;
>>>>       }
>>>>       [tableView insertRowsAtIndexPaths:[NSArray 
>>>> arrayWithObject:[NSIndexPath indexPathForRow:__numRows inSection:0]] 
>>>> withRowAnimation:UITableViewRowAnimationAutomatic];
>>>>       __numRows++;
>>>>       [tableView endUpdates];
>>>>   }];
>>> 
>>> Yeah, this is essentially what I do, but while I can correctly animate the 
>>> frame change alone, if I try to do that AND change contentOffset, it 
>>> doesn't work.
>>> 
>>> Please see the following videos. For reference, the view hierarchy is this: 
>>> 
>>> http://latencyzero.com/stuff/AdjustingOffset.mov
>>> 
>>> The parent View is a blue color. The Container view is green. The 
>>> UITableView is pink.
>>> 
>>> If I do not adjust the content offset (that is, if it gets set to 0.0), you 
>>> can see the views move and resize correctly:
>>> 
>>> http://latencyzero.com/stuff/AdjustingOffset.mov
>>> 
>>> If I DO adjust the content offset (even if I hard-code it to 10 pixels), 
>>> everything ends up in the right place, but the table view immediately 
>>> resizes to the proper height, but the frame.origin.y is adjusted about 81 
>>> pixels down in the view. It snaps to this position, THEN animates to the 
>>> correct position.
>>> 
>>> http://latencyzero.com/stuff/NoOffsetAdjustment.mov
>>> 
>>> The code that does this (for the keyboard appearing) is here:
>>> 
>>> http://pastebin.com/zRSR78fZ
>>> 
>>>>> 
>>>>> 2) When animating a frame change, are subframe re-sizes also animated? It 
>>>>> looks like they're partly immediately update, then animating.
>>>> 
>>>> Any subviews which are resized in the scope of the superview's frame 
>>>> change will share the animation, which includes anything that has 
>>>> autoresizing masks. You may need to invoke -layoutIfNeeded within your 
>>>> animation block on views who defer resizing of their subviews until layout 
>>>> time to capture some things in an animation. But that discussion is 
>>>> orthogonal to your stated goal, which can be achieved by following the 
>>>> sample I've provided above.
>>> 
>>> I tried throwing in a -layoutIfNeeded, but it had no effect.
>>> 
>>> -- 
>>> Rick
>>> 
>>> 
>>> 
>>> 
>>> _______________________________________________
>>> 
>>> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
>>> 
>>> 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:
>>> https://lists.apple.com/mailman/options/cocoa-dev/rmann%40latencyzero.com
>>> 
>>> This email sent to rm...@latencyzero.com
>> 
> 


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to