Reputation: 1512
i'm working on a project where i have a tableview and a uitextfield.
I'm applying the following method when the uitextfield gain/loose the focus :
-(void)enableInset {
CGFloat offSet = -30.0f;
UIEdgeInsets inset = UIEdgeInsetsMake(placesMapView.frame.size.height - offSet, 0.0f, 0.0f, 00.f);
// Updating the tableView position.
placesTableView.contentInset = inset;
placesTableView.contentOffset = CGPointMake(0.0f, -(placesMapView.frame.size.height - offSet));
placesTableView.scrollIndicatorInsets = inset;
}
and
- (void)disableInset {
CGFloat offset = self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;
UIEdgeInsets inset = UIEdgeInsetsMake(offset, 0.0f, 0.0f, 00.f);
placesTableView.contentInset = inset;
placesTableView.contentOffset = CGPointMake(0.0f, -offset);
placesTableView.scrollIndicatorInsets = inset;
}
The enableInset method is called in viewDidLayoutSubviews. then when i call disableInset and enableInset, the UITableView can not be scrolled anymore.
What did i did wrong ? Any idea where i can look for some answer ?
EDIT : If it can help, i added the project on github :
https://github.com/Loadex/PlaceViewer
To re-produce the bug : Scroll the list, tap on the search bar, hit cancel, try to scroll again the list.
Weirdly click on the filter button, when the UIActionSheet is dismissed, the scroll is working again.
Upvotes: 3
Views: 3123
Reputation: 1512
After a few research here is what I noticed:
The TableView when the keyboard is released is not scrolling because the tableview seems to believe that it is displayed on the entire screen. I tried to add more data in the tableview and we can see that the view is scrolling a little.
What I believe happened is that when the keyboard is hidden, some automatic calls are done and messing with what I set in my enableInset method. Here is my working solution:
I registered for the hideKeyboard event:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
and in the callback I called enableInset:
- (void)keyboardDidHide: (NSNotification *) notif{
[self enableInset];
}
And the view is scrolling back again. Any explanation about this are welcome.
Upvotes: 1
Reputation: 478
While looking for a solution to your problem i noticed that the bottom part of the contentInset of your placesTableView kept changing through the different states. It was 0 when in the initial state where you could see the map, and the tableView was behaving as expected. It got set to 216 when the keyboard came up after tapping the search field. I figured this was some automated communication between the tableView and the keyboard (through Notifications or something you did in PlacesQueryTableViewController). This is fine because we want the bottom inset to be set to the top of the keyboard when it appears. Now, here comes the buggy part. When I tapped the cancel button, the contentInset.bottom got set to -216.
I can't quite explain why this happens, but I suspect it has something to do with how that automatic change of the inset is implemented. I suspect that it does something like tableView.contentInset.bottom -= heightOfKeyboard
, and that probably happens when the animation is finished, and not before. The source of your problem is that you change that bottom of contentInset before the animation is done, and thus before that automatic change has happened. So you're setting the bottom to 0 as soon as the user taps cancel. Then the system comes in and reduces it by the height of the keyboard, which turns out to be 216. That's what I think is happening anyway.
To fix this problem, avoid changing the bottom part of the contentInset and just change the top part. placesTableView.contentInset.top
is readOnly, but if you do it like in the code below, you can get around that. I have just changed two lines of code in each method, the ones that have to do with the inset. Hopefully you see what I did.
-(void)enableInset {
NSLog(@"Enabling insets");
// Setting the tableView to overlay the map view
CGFloat offSet = [placestableViewController tableView:placestableViewController.tableView heightForRowAtIndexPath:nil] - 30.0f;
UIEdgeInsets inset = placesTableView.contentInset; // UIEdgeInsetsMake(placesMapView.frame.size.height - offSet, 0.0f, 0.0f, 0.0f);
inset.top = placesMapView.frame.size.height - offSet;
// Updating the tableView position.
placesTableView.contentInset = inset;
placesTableView.contentOffset = CGPointMake(0.0f, -(placesMapView.frame.size.height - offSet));
placesTableView.scrollIndicatorInsets = inset;
placesMapView.hidden = NO;
[placestableViewController loadObjects];}
- (void)disableInset {
NSLog(@"Disable insets");
CGFloat offset = self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;
UIEdgeInsets inset = placesTableView.contentInset;// UIEdgeInsetsMake(offset, 0.0f, 0.0f, 0.0f);
inset.top = offset;
placesTableView.contentInset = inset;
placesTableView.contentOffset = CGPointMake(0.0f, -offset);
placesTableView.scrollIndicatorInsets = inset;
// Hidding the map while in search
placesMapView.hidden = YES;}
.
BTW, if you want to know how I found the contentInset values at the different states, it's quite simple. What I did was to set myself as the delegate of placesTableView in - (void)viewDidLoad
like this placesTableView.delegate = self;
. I also had to change the @interface
statement to @interface KrackMapViewController () <UITableViewDelegate>
to say that we conform to the UITableViewDelegate. Now, here's the trick: UITableViewDelegate conforms to UIScrollViewDelegate. That means we can implement methods of the scroll view delegate. The one that is particularly interesting is this one:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
NSLog(@"Did scroll with insetTop: %f, insetBottom: %f, contentOffset: %f", placesTableView.contentInset.top,
placesTableView.contentInset.bottom,
placesTableView.contentOffset.y);
}
That lets us know when you start dragging the tableView, and in there simply NSLog out the different parameters.
I hope this was helpful. Let me know if this works for you.
Upvotes: 2