拉伸documentView以填充NSScrollView

时间:2015-08-25 19:28:42

标签: autolayout interface-builder swift2 nsscrollview

我想要实现的目标:

在视图内绘制的给定大小的矩形(纸)。 如果它大于视图我希望它可以滚动。 如果它小于视图,我希望它居中。

应在此矩形的顶部绘制形状列表。 如果它们在矩形之外,它们不应该被碾碎但是无论如何都要被绘制。

可滚动区域仅受矩形(纸张)影响,而不受形状影响。因此,不需要绘制可滚动区域外的形状。

我正在使用Swift2.0,自动布局和InterfaceBuilder

我现在拥有的内容:

我在NSScrollView中有一个自定义CanvasView。

如果画布尺寸小于NSScrollView,我使用此技巧使CanvasView居中:https://stackoverflow.com/a/28154936/1533291

我的CanvasView定义如下:

class CanvasView : NSView {
  var canvasSize = Vec2d(x: 100, y: 100) {
    didSet {
      invalidateintrinsiccontentsize()
    }
  }

  var shapes : [MyShape] = []

  override func drawRect(dirtyRect: NSRect) {
    if let context = currentContext {
      let offsetX = (bounds.width-CGFloat(canvasSize.x))/2.0
      let offsetY = (bounds.height-CGFloat(canvasSize.y))/2.0
      CGContextTranslateCTM(context, offsetX, offsetY)

      CGContextSetRGBFillColor(context, 1, 1, 1, 1)
      CGContextFillRect(context, CGRect(x:0,y:0, width: CGFloat(canvasSize.x), height: CGFloat(canvasSize.y)))

      for shape in shapes {
          shape.shape.render(context)
      }
    }
  }

  override var intrinsicContentSize : NSSize {
    return NSSize(width: canvasSize.x, height: canvasSize.y)
  }
}

因此,您可以看到我在画布视图中绘制了所有内容。

问题是如果其中一个形状位于画布之外,它会被剪裁,因为drawRect只能在视图的边界内绘制。

这就是为什么我想拉伸CanvasView,因此它的宽度和高度总是等于或大于滚动视图的大小。但我不知道该怎么做,我甚至不确定这是否是最优雅的方法。

更新:当ScrollView可缩放且缩放系数小于1时,我在下面发布的答案无效。在这种情况下,画布既没有拉伸到完整尺寸也没有居中。我仍然对可缩放Scrollviews的工作解决方案感兴趣。

1 个答案:

答案 0 :(得分:1)

更新:当ScrollView可缩放且缩放系数小于1时不起作用...

经过一些实验,我自己找到了一个有效的解决方案。 核心解决方案非常简单:

  1. 在InterfaceBuilder中创建NSScrollView
  2. 在剪辑视图中指定自定义NSView的类 (您无需设置更改ClipView的类)

  3. 现在添加两个约束:

    1. customView.height> = clipView.height(prio:1000)
    2. customView.width> = clipView.width(prio:1000)
  4. 这是我之前尝试过的,但是它会导致InterfaceBuilder抱怨约束定义不够,因为它不知道对齐是在运行时由NSScrollView本身完成的。

    1. 这就是为什么你需要再添加两个约束:
      1. customView.centerX == clipView.centerX(prio:1000)
      2. customView.centerY == clipView.centerY(prio:1000)
    2. 但由于在运行时不需要这两个约束,您可以为它们选择“在构建时删除”选项

      但即使是现在InterfaceBuilder也在抱怨。它不知道customView的intrinsicSize,即使它是在customView类中定义的。它将宽度/高度约束标记为含糊不清。

      1. 这就是为什么最后你必须为customView的内在大小设置一个占位符。
      2. 现在,InterfaceBuilder很高兴,在运行应用程序时,customView永远不会小于scrollView。

        所有压缩阻力和内容拥抱优先级都可以设置为默认值。

        以下屏幕截图显示了InterfaceBuilder中描述的选项:

        A screenshot of InterfaceBuilder showing of the described options