Cor*_*rey 11 xcode uiscrollview ios autolayout
我试图了解UIScrollView在自动布局环境中的工作原理.到目前为止,我已经尝试阅读Apple文档,Stack Overflow研究,Google研究以及研究Matt Neuberg的工作示例.
Apple 6.1文档说:
UIScrollView对象(或简称为滚动视图)的核心概念是它是一个视图,其原点可在内容视图上调整.它将内容剪辑到其框架,该框架通常(但不一定)与应用程序主窗口的内容重合.滚动视图跟踪手指的移动并相应地调整原点.在滚动视图中"显示"其内容的视图基于新原点绘制其自身的一部分,该原点固定在内容视图中的偏移处.除了显示垂直和水平滚动指示器外,滚动视图本身不进行绘制.滚动视图必须知道内容视图的大小,以便它知道何时停止滚动; 默认情况下,当滚动超出内容范围时,它会"反弹".
基于此,让我们来看看应该如何设置约束.
为了便于讨论,假设我们有3个视图作为一般情况 - 默认主视图控制器视图(A),其子视图是UIScrollview(B),UIScrollview有一个子视图是UIView(C) ).假设我们希望(C)高达1000个单位.
因此,我们进入界面构建器,在故事板中选择视图控制器,并在属性检查器选项卡上将大小更改为自由形式.对于视图(A),(B)和(C),我们在尺寸检查器选项卡上将高度更改为1000.
(A)和主窗口之间的约束
是时候设置约束了.文档明确指出"(Scrollview)将内容剪辑到其框架,通常(......)与应用程序主窗口的内容一致".在我们的示例中,(A)将与应用程序主窗口重合,并且不需要对此进行约束.
(A)和(B)之间的约束
现在文档清楚地知道(B)与(A)完全一致,因此我们将在它们之间设置4个约束,引导空间,尾随空间,顶部空间和底部空间以使用0的常量超视图.
(B)和(C)之间的约束
这里的文档不是那么简单.它说(B)的原点可以在(C)上调整,所以(B)肯定应该小于(C).由于我们知道滚动只是上下移动,我们可以将(B)和(C)之间的左右边界限制为零,我们总是希望它在中间,所以我们将添加一个中心x对齐.我们将在它们之间添加3个约束,将空间和尾随空间引导到superview,常量为0,中心x对齐.为了定位视图,我们需要顶部和底部的东西,老实说,我不确定如何根据文档设置这些约束.在模仿Matt Neuberg的例子的基础上,我将它们作为顶级空间进行超级视图,使用常量零和底部空间来监视默认情况下生成的任何常量.这个超视图约束的底部空间是特殊的(显然),从现在开始它将被称为"specialConstraint".
所以呢?!我们通过说(B)肯定小于(C)来开始这一段,并通过设置约束使它们完全相同的大小来结束它.问题1 - 为什么会这样?
(C)自身的约束
我们知道(C)必须大于(B),以便(B)有东西可以滚动,(C)应该根据自己的约束来确定它的大小.很容易,我们设置1个约束,高度= 1000.
specialConstraint
现在我们在视图控制器中为specialConstraint创建一个出口,在viewDidLoad方法中我们设置self.specialConstraint.constant = 0; 这意味着内容视图的底部应该精确地固定在滚动视图的底部,这样就不会向下滚动.但这在Matt Neuberg的例子中有效.问题2 - 这是为什么?
当Scrollview滚动时,真正发生了什么
我认为合乎逻辑的做法是将滚动视图的框架固定,内容视图的原点(或内容偏移)随滚动移动,内容显示滚动视图,就像一个窗口.类似于通过滑动纸张从墙上的孔中查看纸张.
然而,根据我的阅读,scrollview的框架实际上是在移动,就像固定页面上的放大镜一样.
问题3 - 有人可以解释当滚动视图滚动时发生了什么,该对象的帧起源实际上正在改变,为什么这样做?
问题4 - 任何人都可以用简单的英语解释如何在(A),(B)和(C)之间设置约束条件吗?
小智 0
你好。首先,这是几天前编写的工作代码滚动视图示例。
[self addSubview:scrollView];
id views = NSDictionaryOfVariableBindings(scrollView);
[self addConstraints:PVVFL(@"H:|[scrollView]|").withViews(views).asArray];
[self addConstraints:PVVFL(@"V:|[scrollView]|").withViews(views).asArray];
Run Code Online (Sandbox Code Playgroud)
在Parus lib的帮助下用代码编写的约束。
正如您所提到的,滚动视图与其超级视图相关联。换句话说,它完全填满了它。
前面几行我设置了一scrollView棵树。
id views = NSDictionaryOfVariableBindings(photoView, storeNameLabel, selectStoreButton, tagsLabel, tagsContainer, editTagsButton, commentView, sendButton, cancelButton);
[scrollView addConstraints:PVVFL(@"V:|-15-[photoView(150)]").withViews(views).asArray];
[scrollView addConstraints:PVVFL(@"|-15-[photoView]-15-|").withViews(views).asArray];
[scrollView addConstraint:PVCenterXOf(photoView).equalTo.centerXOf(scrollView).asConstraint];
[scrollView addConstraint:PVTopOf(storeNameLabel).equalTo.bottomOf(photoView).plus(20).asConstraint];
[scrollView addConstraints:
PVVFL(@"|-15-[storeNameLabel]-(>=15)-[selectStoreButton]-15-|")
.alignAllBaseline.withViews(views).asArray];
[selectStoreButton setContentCompressionResistancePriority:UILayoutPriorityRequired
forAxis:UILayoutConstraintAxisHorizontal];
[scrollView addConstraints:
PVVFL(@"V:[storeNameLabel]-15-[tagsLabel][tagsContainer]").alignAllLeft.withViews(views).asArray];
[scrollView addConstraint:PVRightOf(tagsContainer).equalTo.rightOf(selectStoreButton).asConstraint];
[scrollView addConstraint:PVTopOf(editTagsButton).equalTo.bottomOf(tagsContainer).plus(10).asConstraint];
[scrollView addConstraint:PVWidthOf(editTagsButton).equalTo.widthOf(tagsContainer).asConstraint];
[scrollView addConstraint:PVLeftOf(editTagsButton).equalTo.leftOf(tagsContainer).asConstraint];
[scrollView addConstraint:PVTopOf(commentView).equalTo.bottomOf(editTagsButton).plus(10).asConstraint];
[scrollView addConstraint:PVWidthOf(commentView).equalTo.widthOf(editTagsButton).asConstraint];
[scrollView addConstraint:PVLeftOf(commentView).equalTo.leftOf(editTagsButton).asConstraint];
[scrollView addConstraint:PVHeightOf(commentView).moreThan.constant(100).asConstraint];
[scrollView addConstraint:PVLeftOf(cancelButton).equalTo.leftOf(commentView).asConstraint];
[scrollView addConstraints:PVVFL(@"[cancelButton]-(>=15)-[sendButton(==cancelButton)]").alignAllBaseline.withViews(views).asArray];
[scrollView addConstraint:PVRightOf(sendButton).equalTo.rightOf(commentView).asConstraint];
[scrollView addConstraints:PVVFL(@"V:[commentView]-10-[cancelButton]-10-|").withViews(views).asArray];
Run Code Online (Sandbox Code Playgroud)
你看,这是一个非常复杂的布局。但它的要点是:内部视图具有固定的高度,由其内在内容大小提供。综合起来,他们试图增加 的高度scrollView。
但scrollView高度是固定的self.view!约束求解器必须生成错误。但,
苹果对此案例有专门的技术说明。还有一些有趣的时刻:
为了使此功能与自动布局一起使用,滚动视图中的顶部、左侧、底部和右侧边缘现在表示其内容视图的边缘。
本注释还提供了使用滚动视图和自动布局时不同方法的一些示例。
现在我将尝试回答您的问题。
问题 1 - 这是为什么?
正如您在上面所读到的,这是因为滚动视图的自动布局设置内容视图大小而不是帧大小。
问题 2 - 这是为什么?
再说一次,问题在于内容的大小。特殊约束方法看起来像是对接口构建器的破解。在 xib 中,您有正常大小的视图,在 nib 文件实例化后,您只需将一切恢复正常,将此约束固定为 0,这意味着滚动视图的内容大小将等于 C 视图。
问题 3 - 有人可以解释一下滚动视图滚动时发生了什么,哪个对象的框架原点实际上正在改变,以及为什么这样做?
您可以在本文中找到此过程的详细解释:了解滚动视图,但简短的答案是:UIScroll 视图通过更改点执行滚动self.bounds.origin。
问题 4 - 谁能用简单的英语解释如何在 (A)、(B) 和 (C) 之间设置约束?
您应该通过将所有边缘固定到内部视图来设置滚动视图内部的约束。换句话说,滚动视图的所有边缘必须固定两次:通过内部视图和通过超级视图。
如果这个问题的答案还不清楚,你可以从头开始阅读这个答案。