ios UIScrollView 仅在底部禁用垂直反弹

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14084657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:39:34  来源:igfitidea点击:

UIScrollView disable vertical bounce only at bottom

objective-cios

提问by sqreept

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.

我一直在寻找一种方法来禁用 UIScrollView 的垂直反弹,但仅限于底部。我仍然需要在顶部弹跳。

Couldn't find anything. Is this possible?

找不到任何东西。这可能吗?

Thanks in advance!

提前致谢!

回答by Mick MacCallum

Use the UIScrollViewDelegate method scrollViewDidScrollto check the content offset of the scrollview and more or less check if the user is trying to scroll beyond the bottom bounds of the scroll view. Then just use this to set the scroll back to the end of the scroll view. It happens so rapidly that you can't even tell that the scroll view bounced or extended beyond its bounds at all.

使用 UIScrollViewDelegate 方法scrollViewDidScroll检查滚动视图的内容偏移量,并或多或少地检查用户是否试图滚动超出滚动视图的底部边界。然后只需使用它来将滚动设置回滚动视图的末尾。它发生得如此之快,以至于您甚至无法判断滚动视图是否反弹或超出了其边界。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height) {
        [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, scrollView.contentSize.height - scrollView.frame.size.height)];
    }
}

回答by efremidze

To disable vertical bounce at the top in Swift:

在 Swift 中禁用顶部的垂直反弹:

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

回答by sqreept

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

基于 0x7fffffff 的回答,我创建了一个类:

VerticalBounceControl.h

垂直弹跳控件.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

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 UIScrollViewlike this:

可以在调用者不是这样的委托的UIScrollView情况下使用:

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).

通过这种方式,您可以为UIScrollViews设置这种反弹行为,而您不想更改其委托(例如UIWebViews的委托)。

Again, thanks go @0x7fffffff for the solution!

再次感谢@0x7ffffffff 的解决方案!

回答by Jordi Tambillo

Swift 3:

斯威夫特 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
    }
}

回答by 726a

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.

自从我使用分页以来,我一直在寻找一种解决方案,仅针对 contentSize 宽度比设备更宽的滚动视图禁用底部反弹。这些都不适合我,但我找到了一种方法。我想我应该分享这个,因为我浪费了两天时间来做这个。我正在使用 Swift 4,但这适用于目标 c,如果您知道如何转换它,如果您对两者都有经验,这应该很容易。

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 currentPageafter 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 } }

  1. 添加变量以了解滚动视图的当前页面。
    var currentPage : Int!

  2. 设置初始值
    currentPage = 0

  3. currentPage滚动后更新
    public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { let width = scrollView.frame.size.width let page = (scrollView.contentOffset.x + (0.5 * width)) / width currentPage = Int(page) }

  4. 过滤底部滚动并更新 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.ywill filter bottom left and right scrolling

CGFloat(currentPage) * screenWidth < scrollView.contentOffset.x || CGFloat(currentPage) * screenWidth < scrollView.contentOffset.y将过滤左下和右下滚动

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

(((CGFloat(currentPage) * screenWidth - scrollView.contentOffset.x) >= 0) && scrollView.contentOffset.y > 0)将过滤底部中间滚动

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

scrollView.contentOffset.y = 0将阻止它滚动

回答by Tai Le

Let's disable the bounceswhen scroll to the bottom.

让我们禁用bounces滚动到底部的时间。

scrollView.bounces = scrollView.contentOffset.y < scrollView.contentSize.height - scrollView.frame.height

回答by MickeDG

I added fabsf()to 0x7fffffff?'s solution to also cater for negative(downward) scroll:

我添加fabsf()到 0x7ffffffff? 的解决方案也迎合负(向下)滚动:

- (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)];
    }
}