如何保持滚动位置在NSScrollView候变化的规模?
-
18-09-2019 - |
题
我有一个NSView(myView)包裹在一个NSScrollView(myScrollView).使用焦/退的按钮,用户可以改变规模的myView.如果用户目前滚动到一个特定的点在myView,我想让这一部分视屏幕上的后放已经发生。
我已经得到了代码看起来是这样的:
// preserve current position in scrollview
NSRect oldVisibleRect = [[myScrollView contentView] documentVisibleRect];
NSPoint oldCenter = NSPointFromCGPoint(CGPointMake(oldVisibleRect.origin.x + (oldVisibleRect.size.width / 2.0),
oldVisibleRect.origin.y + (oldVisibleRect.size.height / 2.0)));
// adjust my zoom
++displayZoom;
[self scaleUnitSquareToSize:NSSizeFromCGSize(CGSizeMake(0.5, 0.5))];
[self calculateBounds]; // make sure my frame & bounds are at least as big as the visible content view
[self display];
// Adjust scroll view to keep the same position.
NSRect newVisibleRect = [[myScrollView contentView] documentVisibleRect];
NSPoint newOffset = NSPointFromCGPoint(CGPointMake((oldCenter.x * 0.5) - (newVisibleRect.size.width / 2.0),
(oldCenter.y * 0.5) - (newVisibleRect.size.height / 2.0)));
if (newOffset.x < 0)
newOffset.x = 0;
if (newOffset.y < 0)
newOffset.y = 0;
[[myScrollView contentView] scrollToPoint: newOffset];
[myScrollView reflectScrolledClipView: [myScrollView contentView]];
这似乎排序靠近,但它并不完全正确的,我不知道我在做什么错误的。我的两个问题是:
1)有没有一个内置在沿线的东西:
[myView adjustScaleBy: 0.5 whilePreservingLocationInScrollview:myScrollView];
2)如果没有,任何人都可以看到我在做什么错在我的"长周围的方式"的方法,上面?
谢谢!
解决方案
保持同样的滚动位置后的扩展是不容易的。有一件事你需要决定是什么你的意思是"同样"-你想要这顶,中间,或底部可见的地区之前进行扩展以留在原地后伸缩?
或者更直观地说,你想要的位置,留在地方一百分比下降的可见rect等于的百分比,你滚下的文件当你开始(例如,使中心的滚动的大拇指不向上或向下移动在规模、拇指的只是成长或是缩减).
如果你想要后者的效果,做到这一点的方法之一是获得NSScrollView的verticalScroller和horizontalScroller,然后读取他们的'floatValue。这些都是归一化,从0到1,where'0'意味着你在顶部的文件和1意味着你们的结束。好的事情有关要求的滚动是,如果文件是短于NSScrollView,滚动仍然返回的一个理智的回答在所有情况下,对于'floatValue,所以你不需要特殊的情况下这一点。
之后你调整,设置NSScrollView的滚动位置是相同的百分比之前的规模-但遗憾的是,这里就是我的浪我的手一点点。我没有这样做在一段时间,在我的代码,但是我记得你不能就这么设置的NSScrollers''floatValue的直接-他们会看滚动的,但他们实际上不会影响NSScrollView.
所以,你得写一些数学计算出新的左上角文档中基于百分比你想要通过它在y轴上,例如,它会看起来像,"如果该文件是在短于滚动型的内容查看,滚动要点0,否则滚动到一个点((高度的容查看高度documentView)*oldVerticalPercentage)下的文件。" X轴当然是类似的。
此外,我几乎可以肯你不需要一个电话来-在这里显示,一般不应该这么叫它,永远。(-setNeedsDisplay:在大多数。)
-威尔
其他提示
我认为你喜欢打字太多...; - )
// instead of this:
NSPoint oldCenter = NSPointFromCGPoint(CGPointMake(oldVisibleRect.origin.x +
(oldVisibleRect.size.width / 2.0),
// use this:
NSPoint oldCenter = NSMakePoint(NSMidX(oldVisibleRect), NSMaxY(oldVisibleRect));
// likewise instead of this:
[self scaleUnitSquareToSize:NSSizeFromCGSize(CGSizeMake(0.5, 0.5))];
// use this:
[self scaleUnitSquareToSize:NSMakeSize(0.5, 0.5)];
// and instead of this
NSPoint newOffset = NSPointFromCGPoint(CGPointMake(
(oldCenter.x * 0.5) - (newVisibleRect.size.width / 2.0),
(oldCenter.y * 0.5) - (newVisibleRect.size.height / 2.0)));
// use this:
NSPoint newOffset NSMakePoint(
(oldCenter.x - NSWidth(newVisibleRect)) / 2.f,
(oldCenter.y - NSHeight(newVisibleRect)) / 2.f);
这是一个老问题,但我希望有人找这个发现我的回答有用...
float zoomFactor = 1.3;
-(void)zoomIn
{
NSRect visible = [scrollView documentVisibleRect];
NSRect newrect = NSInsetRect(visible, NSWidth(visible)*(1 - 1/zoomFactor)/2.0, NSHeight(visible)*(1 - 1/zoomFactor)/2.0);
NSRect frame = [scrollView.documentView frame];
[scrollView.documentView scaleUnitSquareToSize:NSMakeSize(zoomFactor, zoomFactor)];
[scrollView.documentView setFrame:NSMakeRect(0, 0, frame.size.width * zoomFactor, frame.size.height * zoomFactor)];
[[scrollView documentView] scrollPoint:newrect.origin];
}
-(void)zoomOut
{
NSRect visible = [scrollView documentVisibleRect];
NSRect newrect = NSOffsetRect(visible, -NSWidth(visible)*(zoomFactor - 1)/2.0, -NSHeight(visible)*(zoomFactor - 1)/2.0);
NSRect frame = [scrollView.documentView frame];
[scrollView.documentView scaleUnitSquareToSize:NSMakeSize(1/zoomFactor, 1/zoomFactor)];
[scrollView.documentView setFrame:NSMakeRect(0, 0, frame.size.width / zoomFactor, frame.size.height / zoomFactor)];
[[scrollView documentView] scrollPoint:newrect.origin];
}