将 NSView 覆盖在 NSScrollView 上
我有一个 NSScrollView 填充整个窗口并显示一个巨大的图像。现在我想在滚动视图的部分(例如前 20 个像素高度和窗口宽度)上覆盖自定义 NSView 以显示附加信息。当用户滚动滚动视图时,顶部的自定义 NSView 应保持在原来的位置。
我已尝试以下操作:
- 创建一个窗口大小的 NSView 实例
- 添加 NSScrollView 作为先前生成的 NSView 的子视图
- 将我的自定义视图作为子视图添加到步骤 1 中的 NSView
这在开始时有效,滚动视图正确显示还有我的自定义 NSView。但是,一旦我开始移动滚动视图(滚动),自定义 NSView 就会与 NSScrollView 的内容一起滚动,并最终在其移出边界时消失,并且滚动视图所在的部分会被重绘。我怎样才能有效地将我的自定义 NSView 放在 NSScrollView 之上并确保它保持原状?
谢谢!
I have an NSScrollView that fills an entire window and displays a huge image. Now I would like to overlay a custom NSView over parts of the Scroll View (eg. top 20 Pixels height and window width) to display additional information. As the user scrolls the scroll view, the custom NSView at the top should stay where it is.
I have tried the following:
- Create an instance of NSView of the size of my window
- Add NSScrollView as subview of the previously generated NSView
- Add my custom view as subview to the NSView in step 1
This works in the beginning, the scroll view is displayed properly and my custom NSView as well. However, as soon as I start moving the scroll view (scrolling) the custom NSView is scrolled along with the content of the NSScrollView and eventually disappears when its moved outside of the bounds and the part of scroll view, where it was positioned, becomes redrawn. How could I effectively layer my custom NSView on top of the NSScrollView and make sure it stays put?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您有两个选择:
首先,关闭“滚动复制”。您可以直接在 IB 中执行此操作,也可以通过在
NSScrollView
的contentView
成员上设置copiesOnScroll
选项来执行此操作。默认情况下启用的该选项使得滚动视图“在滚动时复制其现有的渲染图像(仅绘制其文档视图的暴露部分)”。如果关闭,“它会强制每次重新绘制其内容。”因此,如果性能不是一个大问题,可以将其关闭。但是,如果您在滚动视图中进行复杂的绘制,那么每次都必须重新绘制内容可能会导致严重的性能问题。
第二个选项是打开“滚动复制”,然后创建一个包含重叠视图的无边框窗口。这实际上并不像听起来那么黑客,因为您实际上可以添加一个 NSWindow 实例作为当前窗口的子窗口,以便在移动时它会自动与主窗口一起移动。
RoundTransparentWindow 示例将为您提供一个很好的示例接下来创建将包含您的叠加层的窗口。然后,只需使用 NSWindow 的 addChildWindow 将其附加到主窗口即可。
请注意,使用这种方法,您将需要处理覆盖窗口的显示和隐藏的时间。似乎也是这样,当您最大化父窗口时,子窗口位置不会自动调整。所以,你也必须处理这个问题。但是,如果您不想牺牲使用“滚动复制”时有时会带来的巨大性能改进,那么这是一个很好的解决方案。
You have two options:
First, turn off "Copy on Scroll". You can do this directly in IB or by setting the
copiesOnScroll
option on thecontentView
member of theNSScrollView
. That option, which is on by default makes it so the scroll view "copies its existing rendered image while scrolling (only drawing exposed portions of its document view)". If turned off, "it forces its contents to be redrawn each time." So, if performance is not a big issue, it works to just turn that off.However, making it so the content has to redraw every time can cause major performance issues if you are doing complex drawing within the scroll view.
The second option is to leave "Copy on Scroll" turned on and then create a borderless window containing your overlaid view. This is really not as hackish as it might sound as you can actually add an
NSWindow
instance as a child of your current window so that it automatically moves along with the main window when that is moved.The RoundTransparentWindow sample will give you a great example to follow in creating the window that will contain your overlay. Then, simply use NSWindow's
addChildWindow
to attach it to your main window.Note that with this approach you will need to handle the timing of the presentation and hiding of the overlay window. It also seems to be the case that when you maximize the parent window that the child window position does not automatically adjust. So, you'll have to handle that too. But, it's a great solution if you don't want to sacrifice what is sometimes a massive performance improvement when using "Copy on Scroll".
我知道您已经为此找到了一个可行的解决方案,但我最近自己也在寻找同样的事情,并且遇到了 LKOverlayWindow 类,它似乎为这种覆盖提供了一个简单的解决方案。
正如 CocoaDev wiki 中所述,您只需在 Interface Builder 中创建一个新的 NSWindow,让它成为 LKOverlayWindow 的实例,并通过插座附加 NSScrollView 或在代码中指定它。一旦附加到滚动视图,LKOverlayWindow 的内容将覆盖滚动视图并在其移动和调整大小时跟踪它(后者似乎仅与 NSScrollView 作为窗口的出口一起使用)。作者在此处提供了一个示例项目。
我本来打算采用 NSScrollView 子类化的方式,但事实证明这对我来说要容易得多。
I know that you already have a working solution for this, but I happened to be looking for the same thing myself recently and I came across the LKOverlayWindow class by Louis Klaassen, which seems to provide an easy solution for this kind of overlay.
As described on the CocoaDev wiki, you just need to create a new NSWindow in Interface Builder, have it be an instance of LKOverlayWindow, and either attach the NSScrollView through an outlet or specify it in code. Once attached to a scroll view, the contents of the LKOverlayWindow will overlay the scroll view and track it as it moves and is resized (the latter only seems to work with the NSScrollView as an outlet of the window). A sample project is provided by the author here.
I was going to go the way of subclassing NSScrollView, but this turned out to be much easier in my case.