When scrolling, move the entire UIScrollView. When on top, start scrolling as usual

I have a scrollview or actually a UIWebView that is initially placed at 320 pixels at the top of the parent view.

When the user starts scrolling, I want the whole UIWebView to track the upward movement until it reaches the top, then the webview should start scrolling in normal mode. I want this to happen in the same motion of the finger. (That is, the user does not need to lift a finger).

I implemented this with a UIPanGestureRecognizer on top of a UIWebView (see code below). The gesture handler moves the UIWebView and constantly resets the viewOffset scroll content to 0. This works, but the performance is poor, especially if the web view contains a heavy page. I think this is scrolling and resetting the webview, which makes rendering difficult. My solution smells bad, and I suppose there should be a better way?

Do you know any better solution to achieve what I'm trying to do?

@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIWebView *webView;
@property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer;
@property(nonatomic, strong) UIScrollView *webViewScrollView;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *webViewTopMarginConstraint;
@end

@implementation ViewController {
    BOOL gestureEnabled;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    gestureEnabled = YES;

    // Initially put the webview 320 px down on the topview
    self.webView.translatesAutoresizingMaskIntoConstraints = NO;
    self.webViewTopMarginConstraint.constant = 320.0;

    // SET UP GESTURE RECOGNIZER
    _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesturesForWebview:)];
    _panGestureRecognizer.minimumNumberOfTouches = 1;
    _panGestureRecognizer.maximumNumberOfTouches = 1;
    _panGestureRecognizer.delegate = self;
    [self.webView addGestureRecognizer:_panGestureRecognizer];

    // Get hold of the webviews scrollview
    for (UIView* subView in self.webView.subviews) {
        if ([subView isKindOfClass:[UIScrollView class]]) {
            _webViewScrollView = (UIScrollView *)subView;
        }
    }

    // Load a web page in the webview
    NSURLRequest *requestObj = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.macrumors.com"]];
    [self.webView loadRequest:requestObj];
}

- (void)handlePanGesturesForWebview:(UIPanGestureRecognizer *)gesture {

    if (gesture.state == UIGestureRecognizerStateChanged) {
        CGFloat transY = [gesture translationInView:self.view].y; //transY will be negative by the number of pixels panned when panning upwards
        if (gestureEnabled) {
            // Move the whole webview according to gesture movement upwards
            // todo Handle scrolling in the opposite direction
            self.webViewTopMarginConstraint.constant = 320 + transY;
            if (self.webViewTopMarginConstraint.constant <= 0.0) {
                // The webview is at the top, disable the gesture recognizer
                gestureEnabled = NO;
                self.webViewTopMarginConstraint.constant = 0.0;
                self.panGestureRecognizer.delegate = nil;
            }
            // "Rewind" the web scrolling
            CGPoint offset = CGPointMake(0.0, 0.0);
            [self.webViewScrollView setContentOffset:offset animated:NO];
        }
    }
}

#pragma mark UIGestureRecognizerDelegate impl
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}
@end

EDIT: Using an insert like @JPHribovsek suggests that the accepted answer works just fine. The code has also become easier. You can see the solution here: http://gist.github.com/melke/8684172

+4
1

, , scrollview,

CGFloat top = 320.0;     
self.webView.scrollView.contentInset = UIEdgeInsetsMake(top, 0.0, 0.0, 0.0);

, , iOS5 +, scrollview, , , subviews, .

, viewDidLoad :

- (void)viewDidLoad
{
    [super viewDidLoad];

    CGFloat top = 320.0;     
    self.webView.scrollView.contentInset = UIEdgeInsetsMake(top, 0.0, 0.0, 0.0);
    self.webview.scrollView.delegate = self;
    // Load a web page in the webview
    NSURLRequest *requestObj = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.macrumors.com"]];
    [self.webView loadRequest:requestObj];
}

, , , . scrollview . (, bannerView), / , ; , .

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    CGFloat offsetY = scrollView.contentOffset.y;
    //here whatever code you use to set that other view frame position
}
+1

Source: https://habr.com/ru/post/1524162/


All Articles