在UIScrollView中禁用垂直滚动

89

在IB中有一个选项可以取消滚动视图上的垂直滚动,但似乎不起作用。

如何在代码中将滚动视图设置为仅水平滚动而非垂直滚动?


可能是如何禁用iPhone滚动视图的垂直滚动?的重复问题。 - Anurag
13个回答

138

iOS7以来:

第一:内容大小的宽度必须等于您的滚动视图的宽度

第二:在您的initWithNibName中:

self.automaticallyAdjustsScrollViewInsets = NO;

就是这样。


我在我的视图控制器的viewDidLoad方法中添加了这个神奇的东西,解决了一些问题。 - StackRunner
如果你正在使用navigationController,而你的滚动视图在navigationBar的标题后面,就像我的一样,请使用viewDidLoad方法下面的代码。这可以解决问题。 - EFE
1
您可以直接在Storyboard设置中实现相同的效果,无需编写任何代码。只需选择滚动视图控制器并在属性检查器中取消“调整滚动视图插图”。 - Morpheus78
如果你的 UIScrollView 在一个 UICollectionViewCell 中,该怎么办呢? - Skoua
对我来说,将 collectionView 发送到所有视图的前面解决了这个问题。 - Husam
显示剩余3条评论

124

尝试将contentSize的高度设置为scrollView的高度。这样垂直滚动就会被禁用,因为没有内容需要垂直滚动。

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,scrollView.frame.size.height);

你刚刚帮我节省了许多调试这个奇怪问题的时间。谢谢! - jpm
2
@fabb 什么时候知道帧被改变了? - Sam
我认为在自动布局时代,这已经过时了。 - SoftDesigner

49

是的,pt2ph8的答案是正确的,

但是,如果由于某种奇怪的原因,您的contentSize应该高于UIScrollView,则可以实现UIScrollView协议方法来禁用垂直滚动。

 -(void)scrollViewDidScroll:(UIScrollView *)aScrollView;

只需在您的UIViewController中添加此代码

float oldY; // here or better in .h interface

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, oldY)];
    // or if you are sure you wanna it always on top:
    // [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, 0)];
}

这只是在用户滚动UIScrollView时调用的方法,通过这样做,您可以强制其内容始终具有相同的.y值。


7
天啊!请不要像上面的代码一样在 .m 文件中声明 oldY 变量,如 float oldY;。这是 C 风格的变量符号,对于每个应用程序来说,该变量必须作为控制器类的实例成员进行声明。 - Itachi

21

请添加以下方法

-(void)viewDidLayoutSubviews{
    self.automaticallyAdjustsScrollViewInsets = NO;
}

同时将滚动视图的内容大小宽度设置为滚动视图的宽度。


1
这也可以在Storyboard中完成,方法是选择视图控制器并取消勾选属性。 - justColbs
1
我不喜欢这个,因为它会为所有滚动视图设置。希望您可以在不创建新的ScrollView类等情况下,将其具体化为一个图表上的一个滚动视图。 - visc

20

您需要将内容大小参数设置为0来禁用您想要的滚动方向。

要禁用垂直滚动。

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,0);
为禁用水平滚动:
scrollView.contentSize = CGSizeMake(0,scrollView.contentSize.height);

1
这将设置视图的contentSize为您设置的轴上的0。ContentSize是指内容的大小,因此我们希望传入屏幕的高度以禁用超出该框架的垂直滚动。被标记为正确的解决方案是正确的。 - some_id
这对我很有效。将高度设置为contentSize的高度仍然使我垂直滚动。 - KoreanXcodeWorker
1
这对我没有起作用。我还尝试了self.automaticallyAdjustsScrollViewInsets。 - StackRunner
就是这样!将滚动视图的高度设置并没有起作用,但这个方法可以。 - Echizzle

18

我将内容大小更新为禁用垂直滚动,但滚动仍然存在。后来我意识到我还需要禁用垂直弹跳,以完全禁用滚动。

也许有其他人也遇到了这个问题。


你救了我。我的contentSize和frame是一样的,但我怎么也想不出问题在哪里。非常感谢你! - yuf
2
你的回答就是我为什么喜欢stackoverflow的原因! :-) 天哪...这让我抓狂了!你说得对。这是弹跳效果。我想要弹跳效果,但当不需要滚动时就不需要它,所以我将在代码中根据是否需要滚动来禁用/重新启用该效果。 - Erik van der Neut
2
好的,在运行时启用/禁用UIScrollView上的反弹非常容易。在我的情况下,我只关心滚动内容的高度,这个方法很有效:self.scrollView.bounces = (BOOL)(self.scrollView.contentSize.height > self.scrollView.frame.size.height); - Erik van der Neut

12
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x,0)];

}

你必须确认实现了UIScrollViewDelegate

aScrollView.delegate = self;

5

将y设置为始终位于顶部。需要符合UIScrollViewDelegate。

func scrollViewDidScroll(scrollView: UIScrollView) {
        scrollView.contentOffset.y = 0.0
}

这将保持滚动的减速/加速效果。

4
在iOS 11上,如果您想创建一个粘附在屏幕边界而不是安全区域的滚动视图,请记得添加以下内容:
if (@available(iOS 11.0, *)) {
    [self.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}

1
毕竟,非常感谢您!您救了我的一天。 - ha100

2

很多答案都包含将contentOffset设置为0。我有一个情况,我想让scrollView内部的视图居中。这个方法对我很有用:

public func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = -scrollView.contentInset.top
}

在自动布局中运行良好。 - SoftDesigner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接