两个手指拖动与IKImageView和NSScrollView在山狮 [英] Two Finger Drag with IKImageView and NSScrollView in Mountain Lion

查看:441
本文介绍了两个手指拖动与IKImageView和NSScrollView在山狮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Mac应用程序,在应用程序商店已经一年左右。它首次与目标SDK 10.7,狮子一起发布。当更新到Mountain Lion后,它不再工作。

I have a Mac App that's been in the app store for a year or so now. It was first published with target SDK 10.7, Lion. Upon the update to Mountain Lion it no longer works.

应用程序在嵌入NSScrollView的IKImageView中显示大图像。将它放入scrollview的目的是让两个手指拖动工作,而不是用户必须单击拖动。使用Nicholas Riley的ScrollViewWorkaround,我可以使用两个手指滚动来在用户放大后显示剪辑的内容。就像你在预览应用程序中看到的。

The application displays large images in an IKImageView which is embedded in an NSScrollView. The purpose of putting it into a scrollview was to get two finger dragging working, rather than the user having to click to drag. Using ScrollViewWorkaround by Nicholas Riley, I was able to use two finger scrolling to show the clipped content after the user had zoomed in. Just like you see in the Preview app.

Nicholas Riley的解决方案:
IKImageView和滚动条

Nicholas Riley's Solution: IKImageView and scroll bars

现在在山狮这不工作。放大,收缩或缩放按钮后,图像将锁定在图像的左下部分。它不会滚动。

Now in Mountain Lion this doesn't work. After zooming in, pinch or zoom button, the image is locked in the lower left portion of the image. It won't scroll.

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

So the question is, what's the appropriate way to display a large image in IKImageView and have two finger dragging of the zoomed image?

谢谢,

有状态

Thank you,
Stateful

推荐答案

好吧,Nicholas Riley的解决方案是一个丑陋的hack,因为它解决了错误的类;问题不在于 NSClipView (它是子类化的,但它的工作原理很好),但是具有 IKImageView

Well, Nicholas Riley's Solution is an ugly hack in that it addresses the wrong class; the issue isn't with NSClipView (which he subclassed, but which works just fine as is), but with IKImageView.

IKImageView 的问题其实很简单(上帝知道为什么苹果没有固定在什么?... 7年...):它的大小不能调整到图像。现在,当您在 NSScrollView 中嵌入 IKImageView 时,滚动视图显然只能相对于嵌入的 IKImageView ,而不是它包含的图像。由于 IKImageView 的大小始终保持不变,滚动条将无法正常工作。

The issue with IKImageView is actually quite simple (God knows why Apple hasn't fixed this in what? … 7 years ...): Its size does not adjust to the size of the image it displays. Now, when you embed an IKImageView in an NSScrollView, the scroll view obviously can only adjust its scroll bars relative to the size of the embedded IKImageView, not to the image it contains. And since the size of the IKImageView always stays the same, the scroll bars won't work as expected.

以下代码子类 IKImageView 并修复此行为。唉,一旦缩放...

The following code subclasses IKImageView and fixes this behavior. Alas, it won't fix the fact that IKImageView is crash-prone in Mountain Lion as soon as you zoom …

///////////////////// 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

这篇关于两个手指拖动与IKImageView和NSScrollView在山狮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆