UIScrollView分页自动布局和故事板

19

有关使用自动布局的滚动视图以及滚动视图分页的答案很多,但我找不到任何同时解决这两个问题的东西。

我没有尝试做任何花哨的事情...只是想要滚动7张全屏图片视图,并希望能够水平翻页。但出于简单化的考虑(哈!),我决定一步到位地在Storyboard中尝试实现它。

控制器设置为自由形式大小,宽度为2240(320*7)。然后按照Apple建议的方式设置自动布局...

UIScrollview
/-----UIView
/----------Content (7 image views)

滚动视图和其中的UIView都有0/0/0/0约束。当关闭分页效果时,其表现得很好-完全符合预期。但是一旦我开启了分页,滑动会让视图发疯,将整个宽度为2240的区域滚动,然后反弹回来,并最终落在正确的页面上。

我知道我有一个可靠的选择,就是放弃这些并通过编程来实现它,但是我的固执想要找出问题所在。这肯定是有可能的!

3个回答

60

我有一个UIScrollView,它具有分页和AutoLayout功能,并且运行得非常好。这是我的设置:

UIView  // Main view
|---> Dummy UIView   // See below
      |---> UIScrollView
            |---> Content UIView
                  |---> Page 1 Container
                  |---> Page 2 Container

我使用的限制条件是Dummy UIView -> Parent UIView表示我想要分页滚动视图的大小,UIScrollView -> Dummy UIView在四个方向上都是(0,0,0,0)。这只是常规的自动布局,其中创建了一个虚拟 UIView 来放置滚动视图和一个完全填充虚拟 UIView 的 UIScrollView。

有关 AutoLayout 和 UIScrollViews,请参阅苹果的 Technote:https://developer.apple.com/library/content/technotes/tn2154/_index.html

滚动视图内部的内容必须具有固有大小。它不能依赖于滚动视图来获取其大小。

如 TechNote 中所示,将 Content View 的四个边缘约束设置为 UIScrollView 的 (0,0,0,0)。确切的值并不重要,因为您告诉 UIScrollView 的只是从这个视图获取 contentSize。

此时 Xcode 会投诉 Content View 没有固有大小。在这里我们使用上面创建的 Dummy UIView。Dummy UIView 的大小恰好等于 UIScrollView 中每个页面的大小。

因此,我们使用 AutoLayout 将 Content UIView 的高度设置为 Dummy UIView 的高度,并将 Content UIView 的宽度设置为页面数量乘以 Dummy UIView 的宽度。对于后者,请将约束中的乘数更改为页面数量。

现在,按照通常的方式在 Content UIView 中创建页面,并将 UIScrollView 上的 Paging Enabled 设置为是,即可使用 AutoLayout 在 UIScrollView 中进行分页。

我已在 IOS 6、7 和 8 中测试过此方法。

更新:

如请求所示,这里有一个带有此设置的示例项目: https://github.com/kostub/PagingScrollView


8
以下是一个包含上述解决方案的示例项目:https://github.com/kostub/PagingScrollView - Kostub Deshmukh
2
这个答案很棒,而且清晰的示例项目使它变得更好了。 - William Robinson
非常好的方法。此外,如果您需要嵌套滚动视图以实现垂直滚动的分页效果,最好使用xib,在其中将内部滚动视图放置在模拟视图中。 - Juan Reyes
2
如果要展示随时间变化的动态内容,那么这个示例只适用于固定数量的视图,因为它是添加所需的视图数量。 - Imran
@KostubDeshmukh 这对旋转没有帮助。请滚动到第二页并横屏。如果您有解决方案,请告诉我 :) 谢谢 - antonio
很好!它帮助了我 :) - Pushpa Y

11

按照《使用滚动视图构建分页UIScrollView》的方法在Interface Builder中创建带有内容的UIScrollView。

我还建议您使用Stack View作为UIScrollView的内容视图,因为它可以大大减少布局复杂性。

当您使用传统方法时,内容视图内的每个条目视图至少有 5个约束条件:

  • 前导到上一个条目
  • 顶部到父级
  • 尾随到下一个条目
  • 底部到父级
  • 与滚动视图等宽

Stack View会自动排列其内容,因此每个条目应该只有“与滚动视图等宽”的唯一约束条件

Interface Builder Result View

查看此项目https://github.com/eugenebrusov/ios-stack-paging-scroll,以了解Stack View的实际应用。


1
聪明的解决方案是使用堆栈视图作为滚动视图的内容视图! - bcause
我喜欢这个概念,但是视图2和3位于ViewController的右侧,因此在Storyboard上实际上无法看到/编辑。选择VC的“自由形式”会相应地调整UIScrollView和UIStackView的大小,但并没有更好的解决方法。有什么线索吗? - Richard Fairhurst
谢谢你的帮助!这是一个更好的解决方案。再次感谢! - Daniel Arantes Loverde

1

可以使用scrollView的大小来设置contentView的大小,与https://developer.apple.com/library/ios/technotes/tn2154/_index.html相反;这在iOS 8.2 beta 3中进行了测试。

请注意,我是通过编程实现的,但希望对某些人有用。层次结构如下:

root: UIView
  scrollView: UIScrollView
    contentView: UIView
      page0
      page1
      ...
  1. 为scrollView添加约束,使其相对于根视图和scrollView的任何兄弟视图定位。

  2. 将contentView的边缘附加到其父视图(scrollView)上: "H:|[contentView]|"
    "V:|[contentView]|"

  3. 向contentView和scrollView添加大小相等的约束;这是与TN2154相矛盾的部分(其中说“不要依赖滚动视图来获取它们的大小”):

    contentView.height == scrollView.height
    contentView.width == scrollView.width

注意:上述内容是程序化实例化高度约束的虚构符号。

  1. 相对于其父视图(contentView)布局页面;我通过将第一页固定在contentView的左/上部,将后续页面固定在前一页的右/上部来完成此操作。

感谢Koustub让我找到正确的方向-他的解决方案可行,但经过一些调整,我能够消除虚拟视图。


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