1
votes

I have a UIScrollView and a UITableView inside the UIScrollView.

I would like to intercept scrolling of the UITableView and only allow scrolling if the super view (UIScrollView) have reached a specific contentOffset.

I have created subclass of both UIScrollView and UITableView, how do i catch scrolling event and intercepting the scrolling while the user is still scrolling?

Example of what i'm trying to accomplish: The UITableView is going to have a header, if i scroll down the header will collapse to 30% of original size and and stay visible at the top. After i have scrolled back to the top of the UITableView i want the header to expand. In other word i want to extend the scrolling of a UITableView with a header that can collapse/expand.

enter image description hereenter image description here

There might be better way to accomplish this, i'm open for suggestions.

2
How about using scroll view delegate method scrollViewDidScroll:? - Valent Richie

2 Answers

1
votes

There may be a better way, but this solution is working for me.

  • UITableView (let's call it innerScrollView) inside of UIScrollView (let's call it scrollView) inside whatever the main view is (let's call it view).
  • Set an outlet in your view controller for the innerScrollView (self.innerScrollView).
  • Set bounce in XIB or code to: scrollView.bounces = YES and innerScrollView.bounces = NO.
  • Set scrolling to disabled initially for the innerScrollView.
  • In code (viewDidLoad:) set scrollView.contentSize.height to view.frame.size.height + the 70% of the header you want to disappear. Resize innerScrollView to fill the resized contentView to the bottom.
  • Set your view controller as the delegate for scrollView and implement scrollViewDidScroll: as follows:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
       CGFloat maxYOffset = self.scrollView.contentSize.height - self.scrollView.frame.size.height;
       CGFloat minInnerYOffset = self.innerScrollView.contentInset.top;
       CGFloat currentYOffset = scrollView.contentOffset.y;
       CGFloat newYOffsetDelta = currentYOffset - maxYOffset;
       CGFloat currentInnerYOffset = self.innerScrollView.contentOffset.y;
    
       if (scrollView.contentOffset.y >= maxYOffset) {
           self.innerScrollView.scrollEnabled = YES;
           self.scrollView.contentOffset = CGPointMake(0, maxYOffset);
    
           if (currentYOffset != maxYOffset) {
               self.innerScrollView.contentOffset = CGPointMake(0, currentInnerYOffset + newYOffsetDelta);
           }
       }
       else if (currentInnerYOffset > minInnerYOffset) {
           self.scrollView.contentOffset = CGPointMake(0, maxYOffset);
           self.innerScrollView.contentOffset = CGPointMake(0, currentInnerYOffset + newYOffsetDelta);
       }
       else if (currentYOffset < scrollView.contentInset.top) {
           scrollView.contentOffset = CGPointMake(0, scrollView.contentInset.top);
       }
       else {
           self.lowerScrollView.scrollEnabled = NO;
       }
    

    }

I just whipped this up and quickly tested it. It all seems to work, but there may be some improvements and tweaks needed. Regardless, this should get you started at least.

-1
votes

Well, you should use the following UIScrollViewDelegate method

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
   // here perform the action you need
}