UIScrollView自动布局仅垂直方向

36

我想让AutoLayout与UIScrollView配合使用,但遇到了一些问题。以下是我的操作:

  1. 在主视图中添加一个frame为[top: 0,left: 0,width: 320,height: 568]的UIScrollView

  2. UIScrollView中添加一个名为“ContentView”的UIView,并设置其背景色为黑色,frame为[top: 0,left: 0,width: 320,height: 568]。

  3. 设置UIScrollView的约束为:[top: 0, bottom: 0, left: 0, right: 0]。

  4. 设置"ContentView"的约束为:[top: 0, bottom: 0, left: 0, right: 0]。

  5. 对“ContentView”中的项目进行对齐。

  6. 将主视图的背景色设置为灰色(以便查看情况)。

这是一个问题的截图:

屏幕截图1

由于某种原因,约束使内容视图位于屏幕中央。而且它可以在任何方向上滚动。我想让内容只能在垂直方向上像UITableView一样滚动,以便我不能像下面这样移动它:

屏幕截图

我做错了什么?我查看了所有的教程和StackOverflow和Google上的答案,但没有人真正遇到奇怪的问题,所以我请求帮助。

编辑:我还添加了ContentView的宽度和高度作为约束,但也没有帮助。

8个回答

57

你可以完全使用约束来完成这个过程,而且非常容易。

UIScrollView 只需要知道它内部有多少宽度和空间。所以它需要有一些固定在LeadingTrailingTop&Bottom 约束上的内容。此外,内容的宽度和高度需要固定(这并不意味着我必须指定它。我仍然可以使用约束来实现这一点).

  1. 添加一个 UIScrollView 并根据需要进行位置调整。
  2. UIScrollView 中添加一个 UIView 作为内容。
  3. 将内容 UIViewLeadingTrailingTop & Bottom 约束设置为0。
  4. UIScrollViewUIView 添加一个等宽约束。这将使其只能垂直滚动。
  5. 现在需要设置内容 UIView 的高度。然后可以指定内容视图的高度 (或者通过确保底部控件被约束到内容视图的底部,来自适应内容视图中包含的控件的高度)。

我这样做了,它真的很好用。


3
这正是我要找的答案。我的contentView等于UIScrollView的superview。谢谢。 - the Reverend
2
谢谢,等宽约束正是我所需要的。 - William T. Mallard

20

谢谢!水平滚动已禁用。 - Gasim
没问题。关于自动布局的问题,你是在使用Interface Builder还是通过代码使用自动布局? - Derek
我正在使用界面构建器。我将约束左右更改为-16,它起作用了。我不相信这是正确的行为。有没有办法让它在0的情况下工作? - Gasim
我对界面构建器不是很熟悉。通常我会在代码中使用constraintsWithVisualFormat方法。但是,也许可以尝试删除contentView的约束。我通常会在layoutSubviews中为滚动视图内的子视图设置contentView大小。 - Derek
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * _pageCount, self.scrollView.frame.size.height); 这是我过去在uiscrollview中浏览不同视图时的做法。 - Derek

8
总结Leszek S的答案:
为了拥有一个可以垂直滚动的视图,滚动视图中的所有视图都必须设置其宽度约束。很容易将它们设置为滚动视图的超级视图。
原因是只要它的子视图不需要水平滚动,滚动视图就不会水平滚动。例如,如果你有一个标签,设置为0行,自动布局将尝试在开始添加行和换行符之前使标签尽可能宽。如果标签上没有明确的宽度约束,它就会使滚动视图内容区域变宽。对于滚动视图的尾部的约束会被忽略。
如果有很多视图,您可能希望将它们放在单个包含视图中,就像视频中那样。对于我的情况,我只有5或6个标签,它们的高度可以动态改变,但宽度永远不会改变,所以我把它们全部设置为与滚动视图相同的宽度。然后 bingo,我们就得到了一个可以垂直滚动的视图,其中标签根据文本增长或缩小。

8

使用Swift 4-5在Xcode 12.1中测试过的垂直滚动视图设置

  1. 添加一个ScrollView并将顶部、底部、左侧和右侧约束设置为0。 enter image description here
  2. 通过在“Size inspector”中取消选择“Scroll View”中的“Content Layout Guides”来删除它。enter image description here
  3. 向ScrollView添加uiview。 enter image description here

4.我们需要根据ScrollView设置uiview的约束关系。控制点击uiview,然后附加到ScrollView。

enter image description here

  1. 这将显示两者之间的约束关系。

enter image description here

  1. 按住Shift键选择多个,我们需要添加相等的宽度、相等的高度、前导、后续、顶部和底部。

enter image description here

  1. 将“Equal Height”编辑为:Superview优先级由1000更改为250。

enter image description here

  1. 现在添加内容。为简单起见,我在属性检查器中添加了一个图像和一个行数为0的标签,并在viewDidLoad中添加了大量文本。

enter image description here

  1. 最终结果!

enter image description here


3

我编写了一个函数,可以使内容在竖直方向上滚动而不是水平方向上。它创建了一个有限宽度的UIView,并将所有UIScrollView的子视图嵌入其中。

TegScrolledContent.createContentView(scrollView)

https://github.com/exchangegroup/scrollable-content-ios

enter image description here


谢谢您,Evegenii。您的库在我进入横向视图时真的帮了我很多。 - Thiha Aung

2
除了 @derek 的答案,我想补充一点:总是在 scrollViewDidScroll 中设置 contentOffset 会导致性能问题。所以请仅在 x 不为 0 时检查并设置 contentOffset。
    if(contentOffset.x != 0){
        setContentOffset(CGPointMake(0, contentOffset.y), animated: false)
    }

并且需要使用滚动视图

directionalLockEnabled = true

1

为内容视图添加明确的高度和宽度约束


我做了 -> 宽度:568,高度:320。没有运气。 - Gasim
也许您的内容视图被其子视图缩小了。您是否遇到了自动布局异常? - mustafa
不,一个也没有。事情是这样的。我开始尝试使用约束值,并将前导和尾随约束都设为-16,实际上解决了视图在中间的问题...但我真的不想依赖这样的数字。这个问题的原因是什么?你所说的shrinker是什么意思?此外,即使现在滚动视图可以工作,它也不能滚动到期望的位置。 - Gasim

1

下面是我使用的代码片段,用于实现只能垂直滚动的视图。 它的原理是将内容视图作为滚动视图的子视图添加,然后将该内容视图的宽度约束为父滚动视图的宽度。此后,所有子视图都应添加到内容视图而不是滚动视图。

// View that will contain content of scroll view. Width is constrained to the width of the scroll view.
UIView *contentView = [[UIView alloc] init];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
[scrollView addSubview:contentView];

views[@"contentView"] = contentView;
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];
[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
[scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[contentView]|" options:0 metrics:nil views:views]];

// Now, add all your subviews to contentView

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