-->

双手指拖动与IKImageView和NSScrollView在山狮(Two Finger Drag

2019-09-22 02:13发布

我有一个Mac应用程序这一直是在App Store一年左右吧。 这是首次公布与目标SDK 10.7,狮子。 一旦更新,山狮它不再起作用。

应用程序显示在其中嵌入一个NSScrollView大IKImageView图像。 把它变成一个滚动视图的目的是让不必点击拖动双指拖动的工作,而不是用户。 使用ScrollViewWorkaround尼古拉斯·莱利,我可以用两个手指滚动,显示被剪辑内容的用户已经放大了。就像你在预览应用中看到。

尼古拉斯·莱利的解决方案: IKImageView和滚动条

现在在山狮这不起作用。 放大后,捏或缩放按钮时,图像被锁定在图像的左下部分。 它不会滚动。

所以,问题是,什么是在IKImageView显示大图像,并有两个手指拖动缩放图像的适当的方式?

谢谢,
有状态

Answer 1:

好吧,尼古拉斯·莱利的解决方案是一个丑陋的黑客攻击,因为它解决了错误的类; 这个问题是不是与NSClipView(他的子类,但由于是工作得很好),但与IKImageView。

IKImageView这个问题其实很简单(只有天知道为什么苹果公司还没有什么固定的这个... 7年... ...?):它的大小并不适应它显示的图像的大小。 现在,当你在一个NSScrollView嵌入IKImageView,滚动视图显然只能调整相对于嵌入式IKImageView大小的滚动条,而不是它包含的图像。 而且,由于IKImageView的大小始终保持不变,则滚动条将无法正常工作。

下面的代码子类IKImageView并修正这个问题。 可惜的是,它不会修复一个事实,即IKImageView是碰撞容易,只要你放大山狮...

///////////////////// HEADER FILE - FixedIKImageView.h

#import <Quartz/Quartz.h>

@interface FixedIKImageView : IKImageView
@end






///////////////////// IMPLEMENTATION FILE - FixedIKImageView.m

#import "FixedIKImageView.h"


@implementation FixedIKImageView

- (void)awakeFromNib
    {
        [self setTranslatesAutoresizingMaskIntoConstraints:NO]; // compatibility with Auto Layout; without this, there could be Auto Layout error messages when we are resized (delete this line if your app does not use Auto Layout)
    }


// FixedIKImageView must *only* be used embedded within an NSScrollView. This means that setFrame: should never be called explicitly from outside the scroll view. Instead, this method is overwritten here to provide the correct behavior within a scroll view. The new implementation ignores the frameRect parameter.
- (void)setFrame:(NSRect)frameRect
    {
        NSSize  imageSize = [self imageSize];
        CGFloat zoomFactor = [self zoomFactor];
        NSSize  clipViewSize = [[self superview] frame].size;

        // The content of our scroll view (which is ourselves) should stay at least as large as the scroll clip view, so we make ourselves as large as the clip view in case our (zoomed) image is smaller. However, if our image is larger than the clip view, we make ourselves as large as the image, to make the scrollbars appear and scale appropriately.
        CGFloat newWidth = (imageSize.width * zoomFactor < clipViewSize.width)?  clipViewSize.width : imageSize.width * zoomFactor;
        CGFloat newHeight = (imageSize.height * zoomFactor < clipViewSize.height)?  clipViewSize.height : imageSize.height * zoomFactor;

        [super setFrame:NSMakeRect(0, 0, newWidth - 2, newHeight - 2)]; // actually, the clip view is 1 pixel larger than the content view on each side, so we must take that into account
    }


//// We forward size affecting messages to our superclass, but add [self setFrame:NSZeroRect] to update the scroll bars. We also add [self setAutoresizes:NO]. Since IKImageView, instead of using [self setAutoresizes:NO], seems to set the autoresizes instance variable to NO directly, the scrollers would not be activated again without invoking [self setAutoresizes:NO] ourselves when these methods are invoked.

- (void)setZoomFactor:(CGFloat)zoomFactor
    {
        [super setZoomFactor:zoomFactor];
        [self setFrame:NSZeroRect];
        [self setAutoresizes:NO];
    }


- (void)zoomImageToRect:(NSRect)rect
    {
        [super zoomImageToRect:rect];
        [self setFrame:NSZeroRect];
        [self setAutoresizes:NO];
    }


- (void)zoomIn:(id)sender
    {
        [super zoomIn:self];
        [self setFrame:NSZeroRect];
        [self setAutoresizes:NO];
    }


- (void)zoomOut:(id)sender
    {
        [super zoomOut:self];
        [self setFrame:NSZeroRect];
        [self setAutoresizes:NO];
    }


- (void)zoomImageToActualSize:(id)sender
    {
        [super zoomImageToActualSize:sender];
        [self setFrame:NSZeroRect];
        [self setAutoresizes:NO];
    }


- (void)zoomImageToFit:(id)sender
    {
        [self setAutoresizes:YES];  // instead of invoking super's zoomImageToFit: method, which has problems of its own, we invoke setAutoresizes:YES, which does the same thing, but also makes sure the image stays zoomed to fit even if the scroll view is resized, which is the most intuitive behavior, anyway. Since there are no scroll bars in autoresize mode, we need not add [self setFrame:NSZeroRect].
    }


- (void)setAutoresizes:(BOOL)autoresizes    // As long as we autoresize, make sure that no scrollers flicker up occasionally during live update.
    {
        [self setHasHorizontalScroller:!autoresizes];
        [self setHasVerticalScroller:!autoresizes];
        [super setAutoresizes:autoresizes];
    }


@end


文章来源: Two Finger Drag with IKImageView and NSScrollView in Mountain Lion