UIScrollView仅在底部禁用垂直反弹

时间:2012-12-29 18:26:17

标签: objective-c ios

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

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

提前致谢!

7 个答案:

答案 0 :(得分:54)

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

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

答案 1 :(得分:9)

要在Swift顶部禁用垂直反弹:

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

答案 2 :(得分:4)

根据0x7fffffff的回答,我创建了一个类:

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

可以在没有调用者作为UIScrollView的委托的情况下使用,如下所示:

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

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

再次感谢@ 0x7fffffff解决方案!

答案 3 :(得分:0)

我将fabsf()添加到0x7fffffff♦的解决方案也适用于负向(向下)滚动:

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

答案 4 :(得分:0)

斯威夫特3:

这样可以仅在底部禁用垂直反弹:

val rdd = sc.parallelize(Seq(
  (("a", "b"), 1),
  (("a", "c"), 1),
  (("a", "d"), 1),
  (("a", "a"), 1),
  (("k", "k"), 1),
  (("k", "a"), 1),
  (("k", "b"), 1)
))

val rdd1 = rdd.map{ case ((x, y), c) => (x, c) }.
  reduceByKey(_ + _)

scala> rdd1.collect.foreach(println)
(a,4)
(k,3)

val rdd2 = rdd.filter{ case ((x, y), c) => x != y }.
  map{ case ((x, y), c) => (x, c) }.
  reduceByKey(_ + _)

scala> rdd2.collect.foreach(println)
(a,3)
(k,2)

答案 5 :(得分:0)

我一直在寻找一种解决方案来禁用底部反弹,因为我使用的是分页,因此我的contentSize宽度比设备更宽。这些都不适合我,但我找到了一种方法。我想我应该分享这个,因为我浪费了两天才这样做。 我使用的是Swift 4,但这适用于目标c,如果你知道如何转换它,如果你有这方面的经验应该很容易。

这适用于以设备屏幕框架为框架的滚动视图。

  1. 添加变量以了解scrollview的当前页面 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 } }

  5. 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将停止滚动

答案 6 :(得分:0)

滚动到底部时,请禁用bounces

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