NSScrollview 不以编程方式滚动?

Posted

技术标签:

【中文标题】NSScrollview 不以编程方式滚动?【英文标题】:NSScrollview not scrolling programmatically? 【发布时间】:2013-10-30 05:32:53 【问题描述】:

注意:水平和垂直滚动条都在屏幕上可见并且工作正常。但我不能让它们以编程方式移动。

我正在开发一个可可桌面应用程序。我在我的 Mainmenu.xib 文件中使用 NSScrollview,我正在它的所有者中创建一个出口,即 Appdelegate.h 。 这里是出口

@property(nonatomic,retain) IBOutlet NSScrollView* scrollview;

当我尝试从界面生成器设置我的 NSScrollview 的新引用出口并将线路转到文件所有者时,我只看到一个选项“委托”。我没有看到出口滚动视图。 所以我将滚动视图连接到文件所有者中的委托(因为我看不到滚动视图出口)。

现在我正在尝试在我的代码中进行自动滚动。这是代码

for(int a=0;a<10000;a++)

    NSPoint pointToScrollTo = NSMakePoint ( 100+a,100+a );  // Any point you like.
    [[self.scrollview contentView] scrollToPoint: pointToScrollTo];
    [self.scrollview reflectScrolledClipView: [self.scrollview contentView]];

此代码不起作用,滚动条不会自动滚动。

我正在尝试用这段代码制作一个缓慢的滚动动画。

【问题讨论】:

【参考方案1】:

NSClipView 有一个scrollToPoint: 方法,可用于以编程方式滚动:

- (IBAction)scrollToMid:(id)sender

    CGFloat midYPoint = [self.scrollView contentView].frame.size.height/2.0;
    [[self.scrollView contentView] scrollToPoint:NSMakePoint(0.0, midYPoint)];
    [self.scrollView reflectScrolledClipView:[self.scrollView contentView]];

如果你想要动画滚动,你必须通过动画代理设置boundsOrigin。 (因为NSScrollViewNSClipView 都没有暴露动画滚动点属性)

- (IBAction)scrollToMidAnimated:(id)sender

    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration:2.0];
    NSClipView* clipView = [self.scrollView contentView];
    NSPoint newOrigin = [clipView bounds].origin;
    newOrigin.y = [self.scrollView contentView].frame.size.height/2.0;
    [[clipView animator] setBoundsOrigin:newOrigin];
    [NSAnimationContext endGrouping];

【讨论】:

谢谢你的方法有效。投票并被选为最佳答案! 有没有办法限制用户手动滚动? 我不想让用户滚动。我隐藏了滚动条,但用户仍然可以使用鼠标滚动器滚动。这可能吗? 我不希望滚动视图响应用户交互。我只想以编程方式滚动 有没有办法给 clipview 提供最后的分数?即我可以将 x,y 点指定给剪辑视图,而不是给出帧的原点吗?【参考方案2】:

更好的方法是翻转视图。我一直致力于将滚动视图置于顶部。

-(void)scrollToTop:(NSScrollView *)scrollView

    NSPoint newScrollOrigin;
    if ([[scrollView documentView] isFlipped]) 
        newScrollOrigin=NSMakePoint(0.0,0.0);
     else 
        newScrollOrigin=NSMakePoint(0.0,NSMaxY([[scrollView documentView] frame]) -NSHeight([[scrollView contentView] bounds]));
    

    [[scrollView documentView] scrollPoint:newScrollOrigin];

应该在windowDidLoad 中调用以获取位置。

-(void)windowDidLoad

    [super windowDidLoad];
    [self scrollToTop:_myScroll];

【讨论】:

【参考方案3】:

在文件所有者的身份检查器中,检查其类。它必须设置为 NSApplication. 您必须将其更改为 AppDelegate 才能获得可以连接滚动视图的插座 scrollview

但更好的选择是在您的 xib 中有一个 NSObject 并将其类设置为 AppDelegate。 (但是 xcode 默认创建它,检查是否存在项目“AppDelegate”在存在FileOwner 的“占位符”下方的“对象”框中)。现在将引用出口线从您的scrollview 拖到该对象。它将显示您的 Appdelegate 类的 IBOutlet 对象名称。

更新: 您不能使用 for 循环创建慢速动画。 for 循环非常快,以至于您只能看到最终结果,而不是完整的滚动。您需要使用核心动画来进行慢速动画或使用 NSTimer 来延迟滚动以使其变慢。

另外请尝试使用 [scrollview documentView] 代替 [scrollview contentView] 。虽然没试过。

好的,我已经完成了,这是最终结果 如果您的滚动条位于顶部,则以下内容会将其移至末尾:

[scroll.contentView scrollToPoint:NSMakePoint(0, ((NSView*)scroll.contentView).frame.size.height - scroll.contentSize.height)];
[scroll reflectScrolledClipView: [scroll contentView]];

您可以根据需要修改以上内容。

即使您的代码也可以正常工作,但您需要用相对点代替任何点。

因此,不要将代码放在 for 循环中,而是通过在 xib 上拖动一个按钮来测试它,并在其按钮操作中写入:

NSPoint pointToScrollTo = NSMakePoint ( 100,100 );  // Any point you like.
[[scrollview contentView] scrollToPoint: pointToScrollTo];
[scrollview reflectScrolledClipView: [scrollview contentView]];

现在运行应用程序,将滚动视图的滚动设置到某个随机位置。然后单击按钮并检查滚动是否移动到某处。

如果它有效,那么您的代码就可以了,您只需要相应地设置点。它对我有用。

【讨论】:

我已经按照你说的做了,现在我可以将滚动视图连接到插座,但它仍然不起作用 仍然不能以编程方式滚动。我使用了文档视图,但它仍然不起作用【参考方案4】:

我发现如果您使用NSViewController,您需要在viewWillAppear 方法中执行“滚动点”,而不是在viewWillLoad 中。仅供参考。

【讨论】:

主要是因为NSScollView与documentView链接需要时间,后期最好使用scrollPoint或者其他滚动方式

以上是关于NSScrollview 不以编程方式滚动?的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式滚动视图

NSScrollView 滚动后在 Xcode 5 中显示问题

如何设置 NSScrollView 的内容大小?

带有 CA 图层掩码的 NSScrollView 添加了第二个无用的滚动条

如何在 NSScrollView 中控制 NSTableView 的绘制?

如何在 NSScrollView 中强制重绘内容