如何使用Autolayout在我的UIScrollview上设置约束?

use*_*524 173 storyboard uiscrollview ios autolayout

我花了两天时间尝试混合和纯Autolayout方法的各种解决方案,以实现自动布局之前的简单滚动视图设置,现在它已经正式 - 我必须太愚蠢.我主要是在Storyboard中设置它(好吧,它就是这样).

所以这是我的求助.

Viewtree:

UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton
Run Code Online (Sandbox Code Playgroud)

按钮应该水平滚动(从左到右,反之亦然).有人可以让我知道如何设置的约束来实现这个使用纯自动布局???

-

我尝试过混合方法,如下所示:

UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton
Run Code Online (Sandbox Code Playgroud)

...并根据Apple的TechNote contentviewtranslatesAutoresizingMaskIntoConstraints设置和设置设置固定的宽度和高度限制.使用约束设置按钮和滚动视图.这让滚动视图滚动(yay)但是唉,它滚动得太远了!据我所知,滚动宽度在某种程度上比我设置的内容视图加倍了??? !!! ???

我尝试了纯自动布局方法,包括contentview有无.所有观点都是translatesAutoresizingMaskIntoConstraints=NO,除了self.view.按钮具有固定的宽度/高度约束,并固定到滚动视图的所有四个边缘.什么都不滚动.

所以我完全不知道为什么我不能让它正常工作.非常感谢任何帮助,如果您需要任何其他信息,请询问!

更新截图与解决方案 - buttonZ约束:

在此输入图像描述

编辑@ Jamie Forrest 所以解决方案结果是最后一个按钮的错误尾随约束.而不是6441,我设置的值是负数,-6441.棘手的是,在storyboard中设置值时,Pin工具栏中有两个选项:

在此输入图像描述

当前画布值为负(导致无滚动),下面的选项为正(激活滚动).这意味着我不是傻瓜,但我猜至少半盲.虽然,为了我的辩护,XCode没有为"错误"设置显示错误,这有点令人不安吗?

再次编辑 现在这很有趣......将尾随值从-6441(无滚动)更改为6441启用滚动.但我的老朋友"太多内容化"又回来了,导致内容大小是应有的两倍!获取正确内容滚动的解决方案是将尾随约束设置为ZERO!当在Storyboard中工作但是查看@Infinity James的代码时,这并不明显,它应该是什么.

Jam*_*est 65

当你在这里粘贴时,很难看到约束的确切值和设置,所以我不确定你看错了你的截图.

为了解释您的设置中出现了什么问题,我创建了一个基本的示例项目,其中包含与您描述的视图层次结构和约束设置非常相似的视图层次结构和约束设置.水平滚动在示例项目中按预期工作,该项目使用Apple在技术说明中描述的"Pure AutoLayout"方法.

最初让Auto Layout工作时我也遇到了很多麻烦UIScrollView.使其工作的关键是确保滚动视图中的所有项目一起使用具有最终链接到滚动视图的所有侧面的约束,这有助于AutoLayout系统能够为其确定contentSize滚动视图将大于其框架.看起来你试图在你的代码中做到这一点,但也许你有一些多余的约束使得contentSize太小了.

另外值得注意的是,正如其他人所提到的,使用AutoLayout和UIScrollview,您不再显式设置contentSize.AutoLayout系统根据您的约束计算contentSize.

我还发现这个电子书章节非常有助于我理解这一切是如何工作的.希望这一切都有帮助.

  • 遗憾的是我们必须分享截图而不是代码.这只是因为苹果鼓励开发人员使用构建器而不是提供更好的api. (6认同)
  • 完全不直观.开发人员不得不浪费时间和数小时来计算XCode创建者的想法. (4认同)
  • 谢谢您的示例项目!它是有效的,一边看,我一开始找不到任何与我项目有任何区别的东西!我将视图复制到我的项目中,怀疑其他一些设置而不是约束,但它继续工作.这让我注意到我项目中最后一个按钮的尾随约束有一个负面 - 在它前面,而你的正面有一个正值!将 - 更改为正可启用滚动!当我调出Pin工具栏时,有两个选择:使用当前画布值为负值,使用滚动视图(使用当前值)为正...?! (2认同)

bac*_*h-f 48

大声笑欢迎来到愚蠢的俱乐部.我是其中一位创始人.:d

对于VERTICAL滚动:我可以让它工作的唯一方法(iOS 8,Xcode 6和纯自动布局)将以下约束添加到我的滚动视图(所有与superview相关):

  • 等宽
  • 平等高度
  • 中心Y对齐
  • 中心X对齐

我的结构:

  UIView
   - ScrollView
    - Subview
    - Subview
    - Subview
    - Subview
    - ...
Run Code Online (Sandbox Code Playgroud)

这是最终结果:

演示

这是设置:

建立 全屏

这是项目.

希望这可以避免某人在凌晨5点睡着.:d


Sur*_*gch 30

简单的自包含示例

从问题的高票数和答案的票数低来判断,人们在这里找不到可理解的快速解决方案.让我试着添加一个.该项目是一个完全在Interface Builder中完成的自包含示例.你应该能够在10分钟或更短的时间内完成它.然后,您可以将您学到的概念应用到您自己的项目中.

在此输入图像描述

原始问题询问滚动按钮.在这里我只使用UIViews但它们可以代表你喜欢的任何视图.我还选择了水平滚动,因为这种格式的故事板截图更加紧凑.但是,垂直滚动的原理是相同的.

关键概念

  • UIScrollView应该只使用一个子视图.这是一个'UIView',用作内容视图,用于保存您想要滚动的所有内容.
  • 使内容视图和滚动视图的父级具有相等的水平滚动高度.(垂直滚动的宽度相等)
  • 确保所有可滚动内容都具有设置的宽度并固定在所有侧面.

开始一个新项目

它可以只是一个单一的视图应用程序.

故事板

在这个例子中,我们将创建一个水平滚动视图.选择View Controller,然后在Size Inspector中选择Freeform.制作宽度1,000和高度300.这只是让我们在故事板上添加空间来添加将滚动的内容.

在此输入图像描述

添加滚动视图

UIScrollView所有四个边添加并固定到视图控制器的根视图.

在此输入图像描述

添加内容视图

UIView子视图添加到滚动视图.这是关键.不要尝试在滚动视图中添加大量子视图.只需添加一个UIView.这将是您要滚动的其他视图的内容视图.将内容视图固定到四个方面的滚动视图.

在此输入图像描述

平等高度

现在,在"文档大纲"中,Command单击内容视图和滚动视图的父视图,以便同时选择它们.然后将高度设置为相等(Control从内容视图拖动到滚动视图).这也是关键.因为我们是水平滚动,滚动视图的内容视图将不知道应该有多高,除非我们以这种方式设置它.

在此输入图像描述

注意:

  • 如果我们将内容垂直滚动,那么我们将内容视图的宽度设置为等于滚动视图的父宽度.

添加内容

添加三个UIView并给它们所有约束.我用了8点的余量.

在此输入图像描述

约束:

  • 绿色视图:固定顶部,左侧和底部边缘.使宽度为400.
  • 红色视图:固定顶部,左侧和底部边缘.宽度为300.
  • 紫色视图:固定所有四个边缘.无论剩余空间是什么,都要做宽度(在这种情况下为268).

设置宽度约束也是关键,以便滚动视图知道其内容视图的宽度.

成品

就这样.您现在可以运行您的项目.它的行为应该与此答案顶部的滚动图像相似.

对于垂直滚动,只需在此示例中交换所有宽度和高度方向(已测试且正在工作).

进一步研究


Inf*_*mes 9

通过在UIScrollView中应用约束来隐式设置contentSize.

例如,你是否在UIView中有一个UIScrollView它看起来像这样(我相信你知道):

    UIView *containerView               = [[UIView alloc] init];
    UIScrollView *scrollView            = [[UIScrollView alloc] init];
    [containerView addSubview:scrollView];
    containerView.translatesAutoresizingMaskIntoConstraints = NO;
    scrollView.translatesAutoresizingMaskIntoConstraints    = NO;
    NSDictionary *viewsDictionary       = NSDictionaryOfVariableBindings(containerView, scrollView);

    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil
                                                                            views:viewsDictionary]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil
Run Code Online (Sandbox Code Playgroud)

这将设置scrollView以填充containerView的大小(因此containerView必须具有一定的大小).

然后,您可以通过隐式将其设置为足够大以按住这样的按钮来调整UIScrollView的contentSize:

    UIButton *buttonA                   = [[UIButton alloc] init];
    UIButton *buttonB                   = [[UIButton alloc] init];
    UIButton *buttonC                   = [[UIButton alloc] init];
    [scrollView addSubview:buttonA];
    [scrollView addSubview:buttonB];
    [scrollView addSubview:buttonC];
    buttonA.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonB.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonC.translatesAutoresizingMaskIntoConstraints       = NO;

    viewsDictionary                     = NSDictionaryOfVariableBindings(scrollView, buttonA, buttonB, buttonC);

    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[buttonA]-|"
                                                                       options:kNilOptions
                                                                       metrics:nil
                                                                         views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[buttonA]-[buttonB]-[buttonC]-|"
                                                                       options:NSLayoutFormatAlignAllBaseline
                                                                       metrics:nil
                                                                         views:viewsDictionary]];
Run Code Online (Sandbox Code Playgroud)


Dan*_*Liu 8

关于在UIScrollView中使用AutoLayout有很多问题,我们忽略的关键点是UIScrollView的内部视图对内容视图而不是UIScrollView本身进行约束.请参阅技术说明TN2154,您可以找到:

UIScrollView类通过更改其边界的原点来滚动其内容.要使其与"自动布局"一起使用,滚动视图中的顶部,左侧,底部和右侧边缘现在表示其内容视图的边缘.

下图将描述: 在此输入图像描述

您可以发现尾随空间为500个点,如果对UIScrollView进行约束,则视图将被放置并应更新其帧.但是,没有警告也没有错误.因为所有约束都是针对内容视图的.

UIScrollView将根据内部视图的约束来计算内容视图的大小.(例如,内容大小:宽度= 100(前导空格)+ 200(视图宽度)+ 500(尾随空格),高度= 131(顶部间距)+ 200(高度)+ 269(底部间距)

如何在UIScrollView中为视图添加约束:

  1. 在内容视图中对视图的位置进行成像.
  2. 将顶部,右侧,底部,左侧间距添加到内容视图的边缘,此外,还添加这些视图的宽度和高度.

一切都完成了.

使用scrollview处理AutoLayout的一种简单方法是在滚动视图中添加包含所有子视图的容器视图.

结论:使用UIScrollView了解AutoLayout的关键是内部视图对内容视图进行约束,但不对UIScrollView本身进行约束.

附加示例代码


zee*_*wan 5

以下解决方案适用于带有autolayout且没有contentSize的scrollView:

  1. 拖放滚动视图到viewController并应用任何约束来覆盖您想要的空间.
  2. 拖动滚动视图中的UIView并使其覆盖scrollView的整个空间,并将约束应用于scrollView的顶部,左侧,右侧,底部空间.
  3. 根据滚动的需要设置内部视图的高度(如果需要水平滚动,则为宽度).如果需要,也可以从代码中完成此部分.
  4. 关键.将高度设置为点(3)中的某个较大值后,返回到第(2)点并确保将顶部,左侧,右侧,底部值设置回零,因为当您强制Xcode可能已经为您更改了它们在(3)中改变了高度.

而且你已经完成了.现在,您可以在此视图上添加任意数量的控件,并应用彼此相关的约束(如果没有此视图,这些约束似乎不起作用).如果您不想使用此视图,则必须为与scrollView相关的每个控件应用约束(彼此不相关).


势不可挡的小费..............

关键.让我们说清楚UIScrollView是1000宽和100高.(事实上​​,通常这些值是动态的,当然,取决于设备的宽度等.但现在只说1000宽和100高.)假设您正在进行水平滚动.所以在UIScrollView中放置一个UIView.(即"内容视图".)将内容视图顶部,底部,前导,尾随的所有四个约束设置为滚动视图.即使这看起来不对,也要把它们都归零.将内容UIView的高度设置为100并忘记它.现在:您想要水平滚动,因此将内容视图的宽度设置为1225.

请注意,内容视图的宽度现在比父卷轴视图的宽度大225.没关系:事实上,你必须这样做.注意

...你没有将尾随宽度设置为负225 ...

你会认为你必须像往常一样 "匹配"宽度.但是,如果你这样做,它根本不起作用.

您必须将前导和尾随数字设置为零,从不负数(即使宽度为"更大")

有趣的是,你实际上可以将前导/尾随数字设置为任何正值(试着说"50")并且它给你一定的反弹余量.(它通常看起来很棒:尝试一下.)任何一端的任何负值都会"默默地破坏".

令人愤慨的是,经常是Xcode(无论如何都是7.3.1),

将'帮助'为您设置这些值为负数!

因为它试图为你自动计算它们.如果是这样,它会默默地打破.在第一个实例中将所有四个值都设置为零.并且将内容视图的宽度设置为比示例中的"1000"宽得多.


编辑: 我最终使用UITableView而不是UIScrollView满足我的大部分要求.因为tableView在我看来更加灵活和动态.