文档交换时将 NSScrollView 内容设置为左上角而不是左下角

发布于 2024-10-12 06:48:58 字数 1712 浏览 5 评论 0原文

今天,我的一位同事向我提出了一个问题,他如何加载或视图交换 NSScrollViewdocumentView 以便加载的视图看起来能够修复为左上角而不是下角。

他花了一段时间在网上搜索并苦苦挣扎,尽管阅读了 Apple、StackOverflow 和其他各个地方的文档,但仍没有找到解决方案。

下面是逐个解决问题:

在 Interface Builder 中将 NSScrollView 拖到项目中。 另外,在 Interface Builder 中,将两个自定义视图拖到项目中,并添加一些文本字段、按钮等。

使用以下 IBOutlet 创建控制器类(例如 myController):

  • IBOutlet NSScrollView * myScrollView
  • IBOutlet NSView * myCustomView1
  • IBOutlet NSView * myCustomView2

将插座连接到 Interface Builder 中的控件。

创建一个NSView子类来翻转documentView

@implementation myFlippedView

-(id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

-(void)drawRect:(NSRect)dirtyRect {
    // Drawing code here.
}

-(BOOL)isFlipped {
    return YES;
}

在Interface Builder中选择NSScrollViewdocumentView并将其设为myFlippedView 的子类。在 Interface Builder 中,您可以选择 NSScrollView,然后再次单击它以访问 documentView,或者更改 IB 库以显示树视图并选择 NSScrollView< 的子自定义视图/代码>。

myController 类中,使用以下方法交换视图:

-(void)awakeFromNib {

    [myScrollView setDocumentView:myCustomView1];
}

-(IBAction)swapViews:(id)sender {

    if ([myScrollView documentView] == myCustomView1) {

        [myScrollView setDocumentView:myCustomView2];

    } else {

        [myScrollView setDocumentView:myCustomView1];

    }
}

最后将项目中的一个按钮连接到操作 swapViews,构建并运行。

问题是坐标没有按照 isFlipped 的预期进行解析。

I had one of my colleagues come to me today with a problem of how can he load or view-swap a documentView of an NSScrollView so that the loaded view appears to fix to the top-left corner instead of the bottom-let corner.

He had spent a while searching the web and floundering and didn't have a solution despite reading the documentation at Apple, on StackOverflow and various other places.

Here's the issue piece-by-piece:

In Interface Builder drag an NSScrollView into the project.
Also in Interface Builder drag two custom views into the project and add some textfields, buttons etc.

Create a controller class (e.g. myController) with the following IBOutlets:

  • IBOutlet NSScrollView * myScrollView
  • IBOutlet NSView * myCustomView1
  • IBOutlet NSView * myCustomView2

Connect the outlets to the controls in Interface Builder.

Create an NSView subclass to flip the documentView:

@implementation myFlippedView

-(id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

-(void)drawRect:(NSRect)dirtyRect {
    // Drawing code here.
}

-(BOOL)isFlipped {
    return YES;
}

Select the documentViewof the NSScrollView in Interface Builder and make it a subclass of myFlippedView. In Interface Builder you would select the NSScrollView and then click in it again to get to the documentView, or change the IB Library to show a tree view and select the child custom view of the NSScrollView.

In the myController class swap the views with the following methods:

-(void)awakeFromNib {

    [myScrollView setDocumentView:myCustomView1];
}

-(IBAction)swapViews:(id)sender {

    if ([myScrollView documentView] == myCustomView1) {

        [myScrollView setDocumentView:myCustomView2];

    } else {

        [myScrollView setDocumentView:myCustomView1];

    }
}

Finally hook up a button in your project to the action swapViews, build and run.

The problem is that the coordinates were not being resolved as was expected with the isFlipped.

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

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

发布评论

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

评论(2

荭秂 2024-10-19 06:48:58

有一个简单但显然经常被忽视的原因。

尽管 isFlipped 是 Interface Builder 中自定义视图的子类,但 documentView 在视图交换中被替换,其中第一个在 awakeFromNib 上使用。

解决方案是将 myCustomClass1 和 myCustomClass2 子类化为 myFlippedView 类。

执行此操作并测试它,您会注意到视图现在显示在滚动视图的左上角。然而,它产生了一个新问题。自定义视图中的所有内容现在都是从下到上布局的(因为默认情况下所有 NSView 布局都是从左下角开始,所以翻转也会翻转它们的坐标)。

幸运的是,这个问题还有另一个简单的解决方法。继续阅读 :-)

在 Interface Builder 中,突出显示 myCustomView1 中的所有控件,然后从 Layout 菜单中选择 Embed Objects In -->自定义视图。根据需要调整大小,对 myCustomView2 执行相同的操作并重建。

瞧。内容视图交换并出现在滚动视图的左上角而不是左下角的 NSScrollView

There is a simple, but apparently often overlooked reason for this.

Although isFlipped is subclassing the custom view in Interface Builder, the documentView is getting replaced on the view swap, the first of which gets used on awakeFromNib.

The solution is to subclass myCustomClass1 and myCustomClass2 to the myFlippedView class.

Do this and test it and you will notice that the views now appear in the top left of the scroll view. It has, however, created a new problem. All of the content in the custom view is now laid out from bottom to top (because by default all NSView layouts are from bottom left, so flipping also flips their coordinates).

Fortunately there is another easy fix for this problem. Read on :-)

In Interface Builder, highlight all the controls in myCustomView1 and from the Layout menu, select Embed Objects In --> Custom View. Resize as you need to, do the same for myCustomView2 and rebuild.

Voila. An NSScrollView with the content view swapping and appearing at the top-left of the scroll view instead of the bottom left.

淡水深流 2024-10-19 06:48:58

正确地使 documentView 最初与滚动视图的顶部对齐,并在 documentView 小于其 ClipView 时将其固定到顶部,这对我有用:

1 – 在 Interface Builder 中,将 documentView 中的所有控件包含在 自定义 NSView 实例中。 (不是翻转视图)

2 – 创建一个用于 documentViewNSView 子类,并重写这些方法:

- (BOOL)isFlipped {
    return YES;
}
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize {
CGFloat superViewHeight = self.superview.frame.size.height, height = self.frame.size.height;
    if(superViewHeight>height) {
        [self setFrameOrigin:NSMakePoint(self.frame.origin.x, superViewHeight-height)];
    }
}  

子类视图应该是scrollViews 的 documentView 其中包含第二个(普通)NSView,其中包含所有控件。

To correctly make the documentView initially align to the top of the scrollview AND to also pin it to the top when the documentView is smaller than it's clipview, this is what works for me:

1 – In Interface Builder enclose all controls in your documentView in a custom NSView instance. (NOT a flipped view)

2 – Create an NSView subclass to be used for the documentView, and override these methods:

- (BOOL)isFlipped {
    return YES;
}
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize {
CGFloat superViewHeight = self.superview.frame.size.height, height = self.frame.size.height;
    if(superViewHeight>height) {
        [self setFrameOrigin:NSMakePoint(self.frame.origin.x, superViewHeight-height)];
    }
}  

The subclassed view should be the scrollViews' documentView which contains second (normal) NSView that contains all controls.

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