【问题标题】:Stretch documentView to fill NSScrollView拉伸 documentView 以填充 NSScrollView
【发布时间】:2015-11-19 15:43:57
【问题描述】:

我想要达到的目标:

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

应该在这个矩形的顶部绘制一个形状列表。 如果它们在矩形之外,它们不应该被裁剪,但无论如何都应该被绘制。

可滚动区域仅受矩形(纸)影响,不受形状影响。所以在可滚动区域之外的形状就不需要绘制了。

我正在使用 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 的可行解决方案感兴趣。

【问题讨论】:

    标签: autolayout interface-builder swift2 nsscrollview


    【解决方案1】:

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


    经过更多的试验,我自己找到了一个可行的解决方案。 核心解决方案非常简单:

    1. 在 InterfaceBuilder 中创建一个 NSScrollView
    2. 为 Clip View 中的自定义 NSView 指定类 (无需设置更改 ClipView 的类)

    3. 现在添加两个约束:

      1. customView.height >= clipView.height (prio:1000)
      2. customView.width >= clipView.width (prio:1000)

    这是我之前已经尝试过的,但它会导致 InterfaceBuilder 抱怨约束定义不够,因为它不知道对齐是由 NSScrollView 本身在运行时完成的。

    1. 这就是您需要再添加两个约束的原因:
      1. customView.centerX == clipView.centerX(优先级:1000)
      2. customView.centerY == clipView.centerY(优先级:1000)

    但是由于在运行时不需要这两个约束,您可以为它们选择“在构建时删除”选项

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

    1. 这就是为什么最后必须为 customView 的固有大小设置占位符的原因。

    现在 InterfaceBuilder 很高兴,并且在运行应用程序时 customView 永远不会小于 scrollView。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-17
      • 1970-01-01
      • 1970-01-01
      • 2018-06-04
      相关资源
      最近更新 更多