2

I have an application where I have a webview in which I load an HTML page. The html page which I am loading contains 5 pages inside it. Actually when I scroll the webview the scrollViewDidScroll: delegate method of my webview is called where I am checking the offset to get the direction in which the webview is scrolling.

When I scroll the webview to the right I get content offset as 2 and it moves to the next page of html. When I scroll the webview again to the right it shows the content offset as 0 and moves to previous page.

When the direction is right/left I want to call a JavaScript method on webview.

This is my code:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSLog(@"self.webview.scrollView.contentOffset.x:%f",self.webview.scrollView.contentOffset.x);

    NSLog(@"%d",lastContentOffset);
    NSString *val =  @"getPageNo()";
    NSString *val1=  [webview stringByEvaluatingJavaScriptFromString:val];
    int pageno = [val1 intValue];
    NSLog(@"%@",val1);        

    if ( self.webview.scrollView.contentOffset.x==0)
    {       
        //this means webview moves in left direction
        NSLog(@"%f",self.webview.scrollView.contentOffset.x);
        NSLog(@"%d",lastContentOffset);
        NSString *showpageno = [NSString stringWithFormat:@"showPage('%d')",pageno-1];
        [webview stringByEvaluatingJavaScriptFromString:showpageno];
    }
    else if ( self.webview.scrollView.contentOffset.x>0)
    {
        //this means webview moves in right direction
        NSLog(@"%f",self.webview.scrollView.contentOffset.x);
        NSLog(@"%d",lastContentOffset);
        NSString *showpageno = [NSString stringWithFormat:@"showPage('%d')",pageno+1];
        [webview stringByEvaluatingJavaScriptFromString:showpageno];
    }        
}
halfer
  • 19,824
  • 17
  • 99
  • 186
Rani
  • 3,333
  • 13
  • 48
  • 89

3 Answers3

2

Simply use the following in scrollViewDidScroll to detect left / right pan.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGPoint velocity = [[scrollView panGestureRecognizer]velocityInView:scrollView.superview];
    if (velocity.x == 0) {
        return;
    }
    if (velocity.x < -1) {
        // Scrolling left
    } else if (velocity.x > 1) {
        // Scrolling Right 
    }
}

You can use other values than 1 and -1 if you want more flexibility.

Marcio
  • 1,979
  • 15
  • 25
  • 1
    With the disclaimer that [panGestureRecognizer](http://developer.apple.com/library/ios/documentation/uikit/reference/UIScrollView_Class/Reference/UIScrollView.html#//apple_ref/occ/instp/UIScrollView/panGestureRecognizer) depends on iOS 5+ – Nate May 29 '13 at 09:23
0

Subclass UIWebView and override the "didPan" method to get the velocity of the pan gesture.

For example:

 - (void)didPan:(UIGestureRecognizer *)gesture
   {
        UIPanGestureRecognizer *pan=(UIPanGestureRecognizer *)gesture;

        CGPoint vel = [pan velocityInView:self.view];

        if (vel.x > 0)
        {
            // user dragged towards the right
        }
        else
        {
            // user dragged towards the left
        }
    }

Now you can use some Delegation mechanism from within the didPan method to intimate the target class about the direction of scroll.

Sugan S
  • 1,782
  • 7
  • 25
  • 47
Ratikanta Patra
  • 1,177
  • 7
  • 18
0

Disclaimer: you didn't specify which minimum OS you need to support. I generally still support at least iOS 4.3, so for my apps, the panGestureRecognizer property is not available.

In your scroll view delegate, an enum:

typedef enum {
    NONE,
    RIGHT,
    LEFT,
    UP,
    DOWN
} ScrollDirection;

ivars:

float lastContentOffset;
ScrollDirection scrollDirection;

and then

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    static int pageNumber = 0;
    static BOOL firstRun = YES;

    if (lastContentOffset > scrollView.contentOffset.x) {
        scrollDirection = RIGHT;
    } else if (lastContentOffset < scrollView.contentOffset.x) {
        scrollDirection = LEFT;
    }
    lastContentOffset = scrollView.contentOffset.x;
    if (!firstRun) {
        int pageIndex = [self currentScrollPage];
        if (pageIndex != pageNumber) {
            // we've changed pages!
            pageNumber = pageIndex;

            // defer execution to keep scrolling responsive, if 
            //   handlePageChange represents any significant work
            [self performSelector: @selector(handlePageChange) withObject: nil afterDelay:0];
        }
    }
    firstRun = NO;
}

- (void) handlePageChange {
}

-(int)currentScrollPage {
    // NOTE: there's a number of ways to calculate this, that affect
    //  precisely WHEN your delegate triggers the page change handler.
    //  This may not affect you, but could, if scrolling performance is
    //  an issue.

    if (scrollDirection == RIGHT) {
        // round up to delay changeover of pages
        return ceil(fabs(self.scrollView.contentOffset.x) / self.scrollView.frame.size.width);
    } else /* if (scrollDirection == LEFT) */ {
        // round down to delay changeover of pages
        return fabs(self.scrollView.contentOffset.x) / self.scrollView.frame.size.width;
    }
}

Note: your scroll view delegate can get called back many times during a scroll, so normally, I keep track of when the page actually changes, and only perform work when that happens ... not at every little scroll increment. That's why I have the handlePageChange method. You can inspect scrollDirection inside that method if your javascript call depends on the direction.

I don't know if it affects your particular problem, but here's an answer I posted concerning performance in your scroll view delegate.

Community
  • 1
  • 1
Nate
  • 31,017
  • 13
  • 83
  • 207