views:

229

answers:

1

In my app, I have a table view. When the user clicks a button, a UIView overlays part of that table view. It's essentially a partial modal. That table view is intentionally still scrollable while that modal is active. To allow the user to scroll to the bottom of the table view, I change the contentInset and scrollIndicatorInsets values to adjust for the smaller area above the modal. When the modal is taken away, I reset those inset values.

The problem is that when the user has scrolled to the bottom of the newly adjusted inset and then dismisses the modal, the table view jumps abruptly to a new scroll position because the inset is changed instantly. I would like to animate it so there is a transition, but the beginAnimation/commitAnimations methods aren't affecting it for some reason.

Edit: More info. I found the conflict. When presenting the modal, I also hide the navigation bar. The navigation bar natively animates the table view up and down as it shows and hides. When I stop animating the navigation bar, the inset animation works fine. Does anyone know what I can do to work around this conflict? Do I have to wait for the navigation bar animation to finish before adjusting the inset? If so, how to I hook onto that?

Any help is greatly appreciated!

The relevant code from the table view controller is here:

- (void)viewDidLoad {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modalOpened) name:@"ModalStartedOpening" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modalDismissed) name:@"ModalStartedClosing" object:nil];
    [super viewDidLoad];
}

- (void)modalOpened {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    [UIView setAnimationDelegate:self];
    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 201, 0);
    self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, 201, 0);
    [UIView commitAnimations];
}

- (void)modalDismissed {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    [UIView setAnimationDelegate:self];
    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
    self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, 0, 0);
    [UIView commitAnimations];
}
A: 

I found a fix, but it isn't ideal. I wait to show the navigation bar after the inset is done animating. I'm still curious if concurrent animation is possible. Also I would like to know if it is possible to do the reverse. (To call the inset animation after the nav bar is done animating)

Here is the code for my fix:

This is in the Table View Controller:

- (void)modalDismissed {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(modalDismissedEnded:finished:context:)];
    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
    self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, 0, 0);
    [UIView commitAnimations];
}

- (void)modalDismissedEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"InsetFinishedAnimating" object:nil];
}

Then this in the Nav Controller:

- (void)viewDidLoad {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modalDismissed) name:@"InsetFinishedAnimating" object:nil];
    [super viewDidLoad];
}

- (void)modalDismissed {
    [self setNavigationBarHidden:NO animated:YES];
}
Cuzog