我一直在寻找一种方法来禁用 UIScrollView 的垂直反弹,但仅限于底部。我仍然需要在顶部反弹。
找不到任何东西。这可能吗?
提前致谢!
使用 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)];
}
}
要在 Swift 中禁用顶部的垂直反弹:
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView.contentOffset.y < 0 {
scrollView.contentOffset.y = 0
}
}
要在 Swift 中禁用底部的垂直反弹:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.bounds.height {
scrollView.contentOffset.y = scrollView.contentSize.height - scrollView.bounds.height
}
}
根据 0x7fffffff 的回答,我创建了一个类:
垂直弹跳控制.h
#import <UIKit/UIKit.h>
@interface VerticalBounceControl : NSObject
@property (nonatomic, assign) BOOL bounce;
- (id) initWithScrollView:(UIScrollView*)scrollView bounceAtTop:(BOOL)bounceAtTop bounceAtBottom:(BOOL)bounceAtBottom;
@end
垂直弹跳控制.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
不想更改其委托的 s 进行这种反弹行为(例如UIWebView
's one)。
再次感谢@0x7fffffff 的解决方案!
斯威夫特 3:
这仅在底部禁用垂直反弹:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.bounds.height {
scrollView.contentOffset.y = scrollView.contentSize.height - scrollView.bounds.height
}
}
让我们禁用bounces
何时滚动到底部。
scrollView.bounces = scrollView.contentOffset.y < scrollView.contentSize.height - scrollView.frame.height
我添加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)];
}
}
自从我使用分页以来,我一直在寻找一种解决方案,仅针对 contentSize 宽度比设备更宽的滚动视图禁用底部反弹。这些都不适合我,但我找到了一种方法。我想我应该分享这个,因为我浪费了两天时间来做这个。我正在使用 Swift 4,但如果你知道如何转换它,这适用于目标 c,如果你有这两种方法的经验,这应该很容易。
这适用于以设备屏幕框架为框架的滚动视图。
添加变量以了解滚动视图的当前页面。
var currentPage : Int!
设置初始值
currentPage = 0
currentPage
滚动后更新
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let width = scrollView.frame.size.width
let page = (scrollView.contentOffset.x + (0.5 * width)) / width
currentPage = Int(page)
}
过滤底部滚动和更新 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
将过滤左下和右下滚动
(((CGFloat(currentPage) * screenWidth - scrollView.contentOffset.x) >= 0) && scrollView.contentOffset.y > 0)
将过滤底部中间滚动
scrollView.contentOffset.y = 0
将阻止它滚动