有很多关于如何让NSScrollView集中其文档视图的例子。 这是两个例子 (这是如此相似,以至于有人在没有归属的情况下复制某人,但关键是如何。) http://www.bergdesign.com/developer/index_files/88a764e343ce7190c4372d1425b3b6a3-0.html https://github.com/devosoft/avida/blob/master/apps/viewer-macos/src/main/CenteringClipView.h
这通常通过继承NSClipView并覆盖:
来完成 - (NSPoint)constrainScrollPoint:(NSPoint)newOrigin;
但是在Mac OS X 10.9 +
中不推荐使用此方法我们现在能做什么? 哦,不!〜
答案 0 :(得分:21)
嗯,答案很简单,没有那么臃肿。 无论如何,这些都不适用于双击放大。
这样做。它只是有效。 您还可以根据需要自定义调整。
在 @implementation 中,您只需要实现 constrainBoundsRect的覆盖:
- (NSRect)constrainBoundsRect:(NSRect)proposedClipViewBoundsRect {
NSRect constrainedClipViewBoundsRect = [super constrainBoundsRect:proposedClipViewBoundsRect];
// Early out if you want to use the default NSClipView behavior.
if (self.centersDocumentView == NO) {
return constrainedClipViewBoundsRect;
}
NSRect documentViewFrameRect = [self.documentView frame];
// If proposed clip view bounds width is greater than document view frame width, center it horizontally.
if (proposedClipViewBoundsRect.size.width >= documentViewFrameRect.size.width) {
// Adjust the proposed origin.x
constrainedClipViewBoundsRect.origin.x = centeredCoordinateUnitWithProposedContentViewBoundsDimensionAndDocumentViewFrameDimension(proposedClipViewBoundsRect.size.width, documentViewFrameRect.size.width);
}
// If proposed clip view bounds is hight is greater than document view frame height, center it vertically.
if (proposedClipViewBoundsRect.size.height >= documentViewFrameRect.size.height) {
// Adjust the proposed origin.y
constrainedClipViewBoundsRect.origin.y = centeredCoordinateUnitWithProposedContentViewBoundsDimensionAndDocumentViewFrameDimension(proposedClipViewBoundsRect.size.height, documentViewFrameRect.size.height);
}
return constrainedClipViewBoundsRect;
}
CGFloat centeredCoordinateUnitWithProposedContentViewBoundsDimensionAndDocumentViewFrameDimension
(CGFloat proposedContentViewBoundsDimension,
CGFloat documentViewFrameDimension )
{
CGFloat result = floor( (proposedContentViewBoundsDimension - documentViewFrameDimension) / -2.0F );
return result;
}
在@interface中只需添加一个属性。这允许您不使用居中。正如您可以想象的那样,有时可能会出现条件逻辑关闭。
@property BOOL centersDocumentView;
此外,请务必在覆盖
时将此BOOL
设置为YES
或NO
initWithFrame
和initWithCoder:
因此您可以使用已知的默认值。
(记住小孩, initWithCoder:
允许你做一个必要的并在笔尖中设置一个视图的类。不要忘记在你的东西之前调用super! / em>的)
当然,如果你需要支持10.9之前的任何东西,你需要实现其他的东西。
(虽然可能没有其他人那么多......)
答案 1 :(得分:17)
这里是swift的工人阶级
class CenteredClipView:NSClipView
{
override func constrainBoundsRect(proposedBounds: NSRect) -> NSRect {
var rect = super.constrainBoundsRect(proposedBounds)
if let containerView = self.documentView as? NSView {
if (rect.size.width > containerView.frame.size.width) {
rect.origin.x = (containerView.frame.width - rect.width) / 2
}
if(rect.size.height > containerView.frame.size.height) {
rect.origin.y = (containerView.frame.height - rect.height) / 2
}
}
return rect
}
}
答案 2 :(得分:2)
1)确保直接在剪辑视图下的视图(documentView)对剪辑视图没有约束! (如果是,请检查,在构建时删除)
2)子类NSClipView
@implementation CenterClipView
- (NSRect)constrainBoundsRect:(NSRect)proposedClipViewBoundsRect {
NSRect rect = [super constrainBoundsRect:proposedClipViewBoundsRect];
NSView * view = self.documentView;
if (view) {
if (rect.size.width > view.frame.size.width) {
rect.origin.x = (rect.size.width - view.frame.size.width) / 2.;
}
if(rect.size.height > view.frame.size.height) {
rect.origin.y = (rect.size.height - view.frame.size.height) / 2.;
}
}
return rect;
}
@end
3)将NSClipView更改为您的子类
答案 3 :(得分:1)
uchuugaka的上述答案非常有效,正如所指出的,它比旧解决方案简单得多。
上面的代码调用函数centeredCoordinateUnitWithProposedContentViewBoundsDimensionAndDocumentViewFrameDimension()
,但未提供此函数的来源。
这个功能很简单,但为了完整起见,这是一个实现:
CGFloat centeredCoordinateUnitWithProposedContentViewBoundsDimensionAndDocumentViewFrameDimension( CGFloat clipDimension, CGFloat docDimension)
{
CGFloat newOrigin;
newOrigin = roundf((docDimension - clipDimension) / 2.0);
return newOrigin;
}