使用Interface Builder中的“自动布局”启用NSScrollView以滚动其内容

时间:2015-03-24 19:43:04

标签: macos cocoa interface-builder autolayout nsscrollview

我已经实施了一个自定义NSView,其中包含许多NSTextField和其他NSView。然后,我使用Editor>在滚动视图中嵌入了该自定义视图。嵌入>滚动视图。这将在Outline中创建适当的层次结构,但我需要添加Auto Layout约束以指定此滚动视图应放置在视图中的位置(顶部,底部,前导,尾随)。另外,我必须为剪辑视图添加自定义视图的约束,以便在正确的位置布置元素。这很有效,当我运行应用程序时,所有元素都会正确显示,并且视图会弹回滚动。但是,当我减小主视图的高度以使并非所有元素都适合屏幕时,会出现自动布局警告,当我更新帧时,它会再次增加视图的高度。为了解决这个问题,我不得不将滚动视图的底部约束移到主视图中。现在,当我运行应用程序时,窗口设置为正确的大小,但我无法滚动自定义视图以到达内容的底部 - 它受到限制,因此它除了弹性反弹效果之外根本不会滚动,因为你'重新处于边缘限制。所以我的问题是,当我在XIB中布局所有元素并使用自动布局时,我必须做什么才能允许滚动视图滚动?

6 个答案:

答案 0 :(得分:12)

以下是一般方法:

  • 使文档视图至少与剪辑视图一样高。或者,等效地,使剪辑视图不高于文档视图。
  • 允许文档视图在高度上增长,但不会超出其子视图所需的范围。
  • 通过使用低优先级约束来防止文档视图中的歧义,以便在给定其他约束的情况下使其尽可能小。

因此,例如,剪辑视图底部和文档视图底部之间应该存在约束,但它应该是不等式:Superview.Bottom< = Document View.Bottom。 (或者,等效地,Document View.Bottom> = Superview.Bottom。)

在文档视图中,您可能在底部有一些文本字段或某些内容,以及它与文档视图底部之间的约束。使该约束成为不等式:Superview.Bottom> = Text Field.Bottom +标准间距。

这将导致文档视图的高度模糊不清。它可以是足够大的任何尺寸以适合其所有子视图。添加高度约束。将其优先级设置为51并将其常量设置为0.也就是说,它希望使视图具有0高度,但是处于非常低的优先级,因此几乎任何其他东西都将取代它。但它解决了模棱两可的问题。

如果要允许水平滚动,则需要在水平方向上执行相同的常规操作。


更新

还有另一种方法。在文档视图中配置约束以赋予其严格的大小(无不等式)。这通常是从顶部到顶部子视图的一系列约束,从子视图的底部到另一个子视图的顶部等,以及从底部子视图的底部到文档视图&#39 ; s底部。同样导致尾随。

然后,剪辑视图和文档视图之间唯一必要的约束是顶部和前导约束。

如果您在此配置中进行测试,则可以调整大小并滚动滚动视图。所以,这很好。但是,当滚动视图的内容区域高于文档视图时,文档视图将固定到内容区域的底部。在这种情况下,你通常希望它固定在顶部。

原因是剪辑视图未翻转。此外,它调整其边界以匹配文档视图。因此,即使存在将文档视图固定到剪辑视图顶部的约束,剪辑视图的顶部也不是您期望的位置。剪辑视图将文档视图放在(0,0),它位于底部。

因此,最后一部分是创建NSClipView的子类,它会覆盖-isFlipped以返回YES。然后,将NIB中剪辑视图的类设置为子类。在那之后,它将按你的意愿工作。

答案 1 :(得分:1)

对于那些像我一样努力在文档视图和剪辑视图之间设置约束的人: 确保剪辑视图设置为自动布局。 由于神秘的原因,默认情况下未将其设置为自动(至少在Xcode 11中)。下面的尺寸检查器的Cfr屏幕截图。

enter image description here

答案 2 :(得分:0)

我打算从https://stackoverflow.com/a/49947440/2846508重新发布我的答案。

  

有关在代码中使用自动布局的信息,请查看Apple关于自动布局的2012年开发人员会议视频。

     

只需在Interface Builder或代码中使用我在本视频教程中记录的方法:

     

How to use NSScrollView with Auto Layout

     

这是我在此视频中使用的方法:

     
      
  1. 窗口 - 设置委托和IBOutlet属性

  2.   
  3. ScrollView - 固定边缘,无边框,不绘制背景

  4.   
  5. documentView - 固定边0,然后是另一个尾部和底部,clipView≥0@ 499和clipView≤0@ 501,对于documentView的尾随和底部约束

  6.   
  7. 水平堆栈视图中的标签和文本字段,垂直堆栈视图

  8.   
  9. 垂直堆栈视图固定边缘默认,然后是另一个底部,底部≤默认值@ 499并且≥默认值@ 750

  10.   
  11. 水平堆栈视图前导和尾随固定0

  12.   
  13. 标签和文本字段将Y中心与水平堆栈视图对齐

  14.   
  15. 文字字段顶部和底部,尾随2 @ 750,宽度≥100,高度≥22

  16.   
  17. 后续水平堆栈视图前导和尾随固定,对齐文本字段引导

  18.   

答案 3 :(得分:0)

基于Ken Thomases的答案,使用Swift 4,可以将flipped作为用户定义的属性添加到NSClipView,以将内容固定在滚动视图的顶部。

flipped attribute

答案 4 :(得分:0)

为了改善Ken的答案,这是我所做的:

•首先,我读了这篇精彩的tutorial,内容涉及如何使用自动布局在Interface Builder(IB)中设置NSScrollView。

•然后我做了以下事情:

•在IB中创建了一个NSScrollView实例;

•创建了一个新的NSClipView子类,并添加了以下代码:

class ScCalendarClipView: NSClipView {
    open override var isFlipped: Bool {
        return true
    }
} 

•创建了自定义文档视图,并将其作为IB中NSScrollView实例的子代嵌入。

•在我嵌入NSScrollView实例的视图中的IB中添加了以下约束(在这里称为DocumentView

// Right
First Item: SuperView.Trailing
Relation: Less Than or Equal
Second Item: DocumentView.Trailing
Constant: 0
Priority: 510
Multiplier: 1

First Item: SuperView.Trailing
Relation: Greater Than or Equal
Second Item: DocumentView.Trailing
Constant: 0
Priority: 490
Multiplier: 1

// Left
First Item: DocumentView.Leading
Relation: Equal
Second Item: SuperView.Leading
Constant: 0
Priority: 1000
Multiplier: 1

// Bottom (negative constants increase the size of the document view)
First Item: SuperView.Bottom
Relation: Less Than or Equal
Second Item: DocumentView.Bottom
Constant: -600
Priority: 510
Multiplier: 1

// Bottom (constant should be equal to the bottom constraint above)
First Item: SuperView.Bottom
Relation: Greater Than or Equal
Second Item: DocumentView.Bottom
Constant: -600
Priority: 490
Multiplier: 1

// Top
First Item: DocumentView.Top
Relation: Equal
Second Item: SuperView.Top
Constant: 0
Priority: 1000
Multiplier: 1

答案 5 :(得分:0)

NSScrollView必须具有X,Y,宽度和高度约束,以便即使您在NSClipView中具有比ScrollView更大的宽度/高度的视图也要保持其框架不变。

我已经看到,如果您具有更大的视图并且没有这些约束,则NSScrollView的框架会自动设置为与NSClipView相同,这将是一个较大的框架,并且可能会超出窗口的框架。

这就是为什么有时NSScrollView似乎无法滚动的原因,但实际上它足够大,它包含了所有视图,超出了Window的框架,并且不需要滚动。

我通过以下方法使其起作用:

  1. NSScrollView

    设置以下约束
    • 通往集装箱的领先空间
    • 容器的顶部空间
    • 等宽
    • 相等的高度

如下所示

1

  1. NSClipView

    中的每个视图执行相同操作

    如果您要更改NSScrollView的帧大小,则视图还将保留其大小。

就我而言,它就像魅力一样运作!我在ImageView中有一个NSClipView,在您调整窗口大小之后它也会滚动。希望它能起作用!