How to trigger scrollsToTop when UITableView is nested inside UIScrollView
I was wondering if anyone had had any luck triggering scrollsToTop (or by any other means) for a UITableView from the user tapping on the status bar when the UITableView is nested inside a UIScrollView that also obse开发者_高级运维rves this function? I know this probably isn't good practice, but in this instance the UX kind of calls for this type of hierarchy.
Either way, I've seen a whole bunch of proposals ranging from private methods (obviously not going to happen) to adding fake windows over the status bar (also not going to happen).
Ok, so the answer here is two fold:
You cannot have more than one UIScrollView (or classes deriving from or using UIScrollView - i.e. UITableView) on the same UIView with the property scrollsToTop set to YES. Pick the one you want to have the feature and make sure all others are no
For example, do this:
scrollView.scrollsToTop = NO; tableView.scrollsToTop = YES; // or not set
Implement the UIScrollView delegate method
scrollViewShouldScrollToTop:
andreturn YES
if the calling UIScrollView is the UITableView.
Props to this answer for mentioning the non-multiple scrollsToTop
option.
Just wanted to share a little function I wrote that helps debug these situations. As others have mentioned, you have to make sure only ONE scroll view has scrollsToTop turned on. If you embed complex view hierarchies it may be difficult to figure out which scroll view is the culprit. Just call this method after your view hierarchy is created, like in viewDidAppear. The level parameter is just to help indentation and you should seed it off with 0.
-(void)inspectViewAndSubViews:(UIView*) v level:(int)level {
NSMutableString* str = [NSMutableString string];
for (int i = 0; i < level; i++) {
[str appendString:@" "];
}
[str appendFormat:@"%@", [v class]];
if ([v isKindOfClass:[UITableView class]]) {
[str appendString:@" : UITableView "];
}
if ([v isKindOfClass:[UIScrollView class]]) {
[str appendString:@" : UIScrollView "];
UIScrollView* scrollView = (UIScrollView*)v;
if (scrollView.scrollsToTop) {
[str appendString:@" >>>scrollsToTop<<<<"];
}
}
NSLog(@"%@", str);
for (UIView* sv in [v subviews]) {
[self inspectViewAndSubViews:sv level:level+1];
}}
Call it on your view controller's main view.
In the log, you should see >>>scrollsToTop<<< next to every view that has it turned on, making it easy to find the bug.
One thing that helped me fix this problem is:
- Verify every other
UIScollView
in the view hierarchy is set toscollsToTop = NO
- Add sub view controllers as child view controllers using
addChildViewController:
It is not sufficient to only add the view as a subview to the parent's view.
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[gridTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
Hoping to help you :)
精彩评论