将 NSScrollView 与 CALayer 结合使用

发布于 2024-10-03 06:30:40 字数 1382 浏览 1 评论 0原文

我正在尝试创建一个网格样式视图(类似于 NSCollectionView ),但使用 Core Animation 除外。我已经完成了相当多的工作,剩下要做的最后一件事就是实现滚动。

到目前为止,我的设置是有一个 NSView 子类(由层支持),并在初始化时创建并添加 网格层 作为主视图层的子层。我为网格层创建了一个自定义CALayoutManager,它以类似网格的形式排列其子视图。正如预期的那样,当我将子图层添加到网格图层时,会调用布局管理器并自动定位图层。到目前为止,一切都按预期进行。

当我尝试使用 NSScrollView 作为自定义视图的父级来实现滚动时,问题就出现了。我的设置如下:我在 Interface Builder 中创建了自定义视图作为 NSScrollView 的子视图。然后,在我的布局管理器类中,我添加了一个 delegate 属性,并且在初始化期间,我的视图子类将自身设置为布局管理器的委托。在布局管理器的 layoutSublayersForLayer: 方法的末尾,我使用委托方法 layoutManager:contentHeightChanged: 调用其委托。这是我的 NSView 子类中该方法的实现:

- (void)layoutManager:(MyLayoutManager*)manager contentHeightChanged:(CGFloat)height;
{
    CGFloat newHeight = [[self enclosingScrollView] contentSize].height;
    if (height > newHeight) {
        newHeight = height;
    }
    NSRect newFrame = [self frame];
    newFrame.size.height = newHeight;
    [self setFrame:newFrame];
}

非常简单,它只是检查新高度是否大于滚动视图的内容大小,并使用新高度。

这在一定程度上是有效的。当视图调整大小时,它会正确调整视图框架的大小,以封装内容的整个高度,从而使滚动条出现。问题:当在滚动条可见的情况下调整视图大小时,网格层的子层会抖动。这是显示问题的视频:

http://vimeo.com/16987653

可以看到,当滚动条不可见时(换句话说,当内容的高度适合滚动视图的边界时),就没有问题。我可以确认这不是布局管理器和处理单列的问题,因为我在没有滚动视图的情况下测试了同样的事情,并且没有抖动。

非常感谢任何建议。

I'm attempting to create a grid style view (similar to NSCollectionView), except using Core Animation. I'm pretty far through it, and the last major thing left to do is implement scrolling.

My setup so far is that I have an NSView subclass (layer backed), and upon initialization it creates and adds the grid layer as a sublayer of the main view layer. I have created a custom CALayoutManager for the grid layer that arranges its subviews in a grid-like formation. As expected, when I add sublayers to the grid layer, the layout manager is called and the layers are positioned automatically. Up to this point, everything is working as it should.

The problem comes when I try to use an NSScrollView as a parent of my custom view to implement scrolling. I set this up as follows: I created my custom view as a subview of the NSScrollView in Interface Builder. Then, in my layout manager class, I added a delegate property and during initialization, my view subclass sets itself as the delegate of the layout manager. At the end of the layoutSublayersForLayer: method of the layout manager, I call upon its delegate with the delegate method layoutManager:contentHeightChanged:. Here is the implementation of that method in my NSView subclass:

- (void)layoutManager:(MyLayoutManager*)manager contentHeightChanged:(CGFloat)height;
{
    CGFloat newHeight = [[self enclosingScrollView] contentSize].height;
    if (height > newHeight) {
        newHeight = height;
    }
    NSRect newFrame = [self frame];
    newFrame.size.height = newHeight;
    [self setFrame:newFrame];
}

It's pretty simple, it just checks to see whether the new height is larger than the content size of the scroll view, and sets the views frame with the new height.

This works — to a certain extent. When the view resizes, it sizes the view's frame properly as it should to encapsulate the full height of the content, thereby making scrollbars appear. The problem: the sublayers of the grid layer jitter when the view is being resized with the scrollbars visible. Here's a video showing the problem:

http://vimeo.com/16987653

As you can see, there is no issue when the scrollbars aren't visible (in other words, when the height of the content fits within the bounds of the scroll view). I can confirm that this isn't a problem with the layout manager and dealing with single columns, because I tested the same thing without the scroll view and there are no jitters.

Any advice is greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

So尛奶瓶 2024-10-10 06:30:40

通过翻转图层和视图的坐标系(原点在左上角)解决了这个问题。

Solved this problem by flipping the coordinate system of both the layer and the view (origin at top left corner).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文