Prevent uiscrollview from scrolling further then c

2019-03-21 07:09发布

问题:

This question already has an answer here:

  • Limiting the scrollable area in UIScrollView 4 answers

I have a UIScrollView which has subviews that create a content with a width of about 7000. Now I want the UIScrollView to not scroll any further then 2000.

I tried:

[scrollView setContentSize:CGSizeMake(768.0, 2000.0)];  
[scrollView setClipsToBounds:YES];

But I can still scroll to the end, how do I prevent this?

回答1:

It's seems that webView is changing its scrollView contentSize after page loading.

In your init set self as a delegate of WebView:

[webView setDelegate: self];

And add this method:

- (void)webViewDidFinishLoad: (UIWebView *)webView {
    [webView.scrollView setContentSize: CGSizeMake(768.0, 2000.0)]; 
}

In my test case it's working fine.


UPDATED:

Calling javascript methods sometimes does not trigger webViewDidFinishLoad. So the most universal technique will be Key-Value Observing.

In init:

[webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];

And somewhere this method:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    UIScrollView * scrlView = (UIScrollView *) object;
    if ([keyPath isEqual:@"contentSize"]) {
        NSLog(@"New contentSize: %f x %f",scrlView.contentSize.width,scrlView.contentSize.height);
        if(scrlView.contentSize.width!=768.0||scrlView.contentSize.height!=2000.0)
        [scrlView setContentSize:CGSizeMake(768.0, 2000.0)]; 
    }
}

Do not forget to remove observer in case of dealloc:

[webView.scrollView removeObserver:self forKeyPath:@"contentSize"];


回答2:

You can set content offset to 2000 if it is more than 2000 so it won't go beyond the bound.

Implement this method and set it to the delegate of that scrollview

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.contentOffset.x > 2000) {
        CGPoint offset = scrollView.contentOffset;
        offset.x = 2000;
        [scrollView setContentOffset:offset animated:YES];
    }
}

Edit: I just tried this, and it works fine. Maybe check why setContentSize: is not working? Another approach, make a view with heigh of 2000, put your content view inside it, and add that view as subview of scrollview.

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 600, 7000)];
label.numberOfLines = 60;
label.font = [UIFont systemFontOfSize:100];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];

NSMutableString *str = [[NSMutableString alloc] initWithCapacity:300];
for (int i = 0; i < 60; i++)
    [str appendFormat:@"%d\n", i];
label.text = str;

[scrollView addSubview:label];
[scrollView setContentSize:CGSizeMake(600, 2000)];
[self.view addSubview:scrollView];


回答3:

I believe your code above should work fine. setContentSize will prevent the contentOffset from getting larger. You may have to start, though, by setting contentOffset yourself (once) if the user has already scrolled outside that area. (Try resetting it to (0, 0), for example.)

Also, are you permitting zooming? If you have a zoom != 1, the content size may not be what you think it is. Try setting zoom to 1 before modifying the content size.



回答4:

Ok So first step, your view controller must implement UISCrollViewDelegate, and you must set your controller as a delegate for your UIScrollView.

Then, implement this delegate method in your controller:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    static float stopx = 2000.0f;

    if (scrollView.contentOffset.x >= stopx) {
        CGPoint stop = scrollView.contentOffset;
        stop.x = stopx;
        [scrollView setContentOffset:stop animated:NO];
    }
}

Anytime you get pass 2000 / stops value, the scrollview should be brought back



回答5:

As others have said, implement the uiscrollviewdelegate

implement these methods:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

and hopefully that will fix the jumping issue you were having

note, put in these methods similar code to the other posts like

static float stopx = 2000.0f;

if (scrollView.contentOffset.x >= stopx) {
    CGPoint stop = scrollView.contentOffset;
    stop.x = stopx;
    [scrollView setContentOffset:stop animated:NO];
}

At first performance will possibly be compromised, if this is true, begin taking out certain delegate methods until you get the desired behavior



回答6:

Unless I'm misunderstanding something in your question this is straightforward. Add this to your view controller containing the web view.

- (void)viewDidLoad
{
    // other stuff
    self.webView.delegate = self;
    self.webView.scrollView.bounces = YES;
    // load your webView here
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    CGSize contentSize = self.webView.scrollView.contentSize;
    CGFloat maxContentWidth = contentSize.width;
    if (maxContentWidth > 2000) {
        maxContentWidth = 2000;
    }
    self.webView.scrollView.contentSize = CGSizeMake(maxContentWidth, contentSize.height);
}


回答7:

Hard to give specific answer without seeing your html but I've had a similar problem before and i think its actually your UIWebview thats actually scrolling and not the scrollview. somewhere on the page in the UIWebview html you will most probably have oversize content. THe webview naturally wants to scroll. In my case it was a long URL in a paragraph of text. I have also seen this happening vertically.

You need to find the container element to your oversize html and set the overflow to hidden in the css. It may be that this is the body tag or the html tag in the html or you need to wrap your content.

ie;

<div style="overflow:hidden">
    Overflowing text
</div>

Failing that you may have to play with the following tag

Or set the container div to width:100% & height:100%;