UIScrollView disable vertical bounce only at bottom

后端 未结 7 625
被撕碎了的回忆
被撕碎了的回忆 2020-12-29 04:26

I\'ve been searching for a way to disable vertical bounce for a UIScrollView but only at bottom. I still need to have the bounce at the top.

Couldn\'t find anything.

相关标签:
7条回答
  • 2020-12-29 04:58

    Based on 0x7fffffff's answer I've created a class:

    VerticalBounceControl.h

    #import <UIKit/UIKit.h>
    
    @interface VerticalBounceControl : NSObject
    
    @property (nonatomic, assign) BOOL bounce;
    
    - (id) initWithScrollView:(UIScrollView*)scrollView bounceAtTop:(BOOL)bounceAtTop bounceAtBottom:(BOOL)bounceAtBottom;
    
    @end
    

    VerticalBounceControl.m

    #import "VerticalBounceControl.h"
    
    @interface VerticalBounceControl ()
    @property (nonatomic, retain) UIScrollView* scrollView;
    @property (nonatomic, assign) BOOL bounceAtTop;
    @property (nonatomic, assign) BOOL bounceAtBottom;
    @end
    
    @implementation VerticalBounceControl
    
    - (id) initWithScrollView:(UIScrollView*)scrollView bounceAtTop:(BOOL)bounceAtTop bounceAtBottom:(BOOL)bounceAtBottom {
        self = [super init];
        if(self) {
            self.bounce = YES;
            self.scrollView = scrollView;
            self.bounceAtTop = bounceAtTop;
            self.bounceAtBottom = bounceAtBottom;
            [self.scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:NULL];
        }
        return self;
    }
    
    - (void) dealloc {
        [self.scrollView removeObserver:self forKeyPath:@"contentOffset"];
        self.scrollView = nil;
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        if ([keyPath isEqualToString:@"contentOffset"]) {
            if (self.bounce && ((self.scrollView.contentOffset.y<=0 && self.bounceAtTop) || (self.scrollView.contentOffset.y>=self.scrollView.contentSize.height-1 && self.bounceAtBottom))) {
                self.scrollView.bounces = YES;
            } else {
                self.scrollView.bounces = NO;
            }
        }
    }
    
    @end
    

    that can be used without the caller being a delegate of UIScrollView like this:

    VerticalBounceControl* bounceControl = [[VerticalBounceControl alloc] initWithScrollView:anyScrollView bounceAtTop:YES bounceAtBottom:NO];
    

    This way you can have this bounce behavior for UIScrollViews that you don't want to alter their delegate (like UIWebView's one).

    Again, thanks go @0x7fffffff for the solution!

    0 讨论(0)
  • 2020-12-29 04:59

    I have been looking a solution to disable bottom bounce only for a scrollview with wider contentSize width than device since I am using paging. None of those work for me but I found a way to do it. I thought I should share this since I wasted two days just to do this. I am using Swift 4 but this applies to objective c if you know how to convert this which should be easy if you have experience with both.

    This works in a scrollview with device screen frame as frame.

    1. Add variable to be aware for scrollview's current page.
      var currentPage : Int!

    2. Set initial value
      currentPage = 0

    3. Update currentPage after scrolling
      public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { let width = scrollView.frame.size.width let page = (scrollView.contentOffset.x + (0.5 * width)) / width currentPage = Int(page) }

    4. Filter bottom scrolling and update contentOffset
      public func scrollViewDidScroll(_ scrollView: UIScrollView) { if CGFloat(currentPage) * screenWidth < scrollView.contentOffset.x || CGFloat(currentPage) * screenWidth < scrollView.contentOffset.y || (((CGFloat(currentPage) * screenWidth - scrollView.contentOffset.x) >= 0) && scrollView.contentOffset.y > 0){ scrollView.contentOffset.y = 0 } }

    CGFloat(currentPage) * screenWidth < scrollView.contentOffset.x || CGFloat(currentPage) * screenWidth < scrollView.contentOffset.y will filter bottom left and right scrolling

    (((CGFloat(currentPage) * screenWidth - scrollView.contentOffset.x) >= 0) && scrollView.contentOffset.y > 0) will filter bottom mid scrolling

    scrollView.contentOffset.y = 0 will stop it from scrolling

    0 讨论(0)
  • 2020-12-29 05:00

    To disable vertical bounce at the top in Swift:

    func scrollViewDidScroll(scrollView: UIScrollView) {
        if scrollView.contentOffset.y < 0 {
            scrollView.contentOffset.y = 0
        }
    }
    

    To disable vertical bounce at the bottom in Swift:

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.bounds.height {
            scrollView.contentOffset.y = scrollView.contentSize.height - scrollView.bounds.height
        }
    }
    
    0 讨论(0)
  • 2020-12-29 05:09

    Swift 3:

    This works to disable vertical bounce only at the bottom:

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.bounds.height {
            scrollView.contentOffset.y = scrollView.contentSize.height - scrollView.bounds.height
        }
    }
    
    0 讨论(0)
  • 2020-12-29 05:09

    Let's disable the bounces when scroll to the bottom.

    scrollView.bounces = scrollView.contentOffset.y < scrollView.contentSize.height - scrollView.frame.height
    
    0 讨论(0)
  • I added fabsf() to 0x7fffffff♦'s solution to also cater for negative(downward) scroll:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        if (fabsf(scrollView.contentOffset.y) >= scrollView.contentSize.height - scrollView.frame.size.height) {
            [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, scrollView.contentSize.height - scrollView.frame.size.height)];
        }
    }
    
    0 讨论(0)
提交回复
热议问题