简体   繁体   English

在Mac OS X Lion中禁用WebView中的滚动动画?

[英]Disable scrolling animation in a WebView in Mac OS X Lion?

How do you disable the animation that occurs when you use the arrow keys to navigate within a WebView in Mac OS X Lion? 当您使用箭头键在Mac OS X Lion中的WebView中导航时,如何禁用发生的动画?

The behavior I'm trying to change appears to be the default for WebViews on Mac OS X Lion. 我试图更改的行为似乎是Mac OS X Lion上WebViews的默认行为。 If you load a document into a WebView, set the insertion point, and then use the Up Arrow and Down Arrow keys to navigate, scrolling is not instantaneous — there's an animation (the view visibly scrolls up or down). 如果将文档加载到WebView中,请设置插入点,然后使用向上箭头键和向下箭头键进行导航,滚动不是即时的 - 有动画(视图可以向上或向下滚动)。

Here's an Xcode project you can use to see this behavior (just run the application, set the insertion point within the document, and then use the Up Arrow and Down Arrow keys to navigate such that the view scrolls): http://dl.dropbox.com/u/78928597/WebViewTest.zip 这是一个Xcode项目,您可以使用它来查看此行为(只需运行应用程序,在文档中设置插入点,然后使用向上箭头和向下箭头键进行导航以使视图滚动): http:// dl。 dropbox.com/u/78928597/WebViewTest.zip

The behavior I'm trying to achieve is what happens in Safari. 我想要实现的行为就是在Safari中发生的事情。 If you open an html document whose contenteditable attribute is set to true in Safari, you can set the insertion point within the document, and then navigate by using the Up Arrow and Down Arrow keys. 如果在Safari中打开其contenteditable属性设置为true的html文档,则可以在文档中设置插入点,然后使用向上箭头键和向下箭头键进行导航。 When you navigate in this way, scrolling is not animated. 以这种方式导航时,滚动不是动画。 The view scrolls instantaneously. 视图即时滚动。

Here is an html document you can use to see this behavior: http://dl.dropbox.com/u/78928597/WebViewTest.html 这是一个html文档,您可以使用它来查看此行为: http//dl.dropbox.com/u/78928597/WebViewTest.html

Since Safari uses a WebView, and it scrolls instantaneously, it seems like there should be a way to change the scrolling behavior of any WebView, but I've had no luck in finding it. 由于Safari使用WebView,并且它即时滚动,似乎应该有一种方法来改变任何WebView的滚动行为,但我没有找到它的运气。

Note that you need to set the insertion point before you navigate with the arrow keys, otherwise you'll see different behavior. 请注意,您需要在使用箭头键导航之前设置插入点,否则您将看到不同的行为。

I think there is a way to do this, but it requires using the Objective-C runtime to modify a private method of a private class. 我认为有一种方法可以做到这一点,但它需要使用Objective-C运行时来修改私有类的私有方法。

To use the Objective-C runtime, add 要使用Objective-C运行时,请添加

#import <objc/runtime.h>

to the #import directives at the top of AppDelegate.m in your Xcode project. 到Xcode项目中AppDelegate.m顶部的#import指令。

Scroll animation appears to occur in the private method 滚动动画似乎发生在私有方法中

- (BOOL)_scrollTo:(const CGPoint *)pointRef animate:(NSInteger)animationSpecifier flashScrollerKnobs:(NSUInteger)knobFlashSpecifier

of NSClipView . NSClipView

We cannot modify the NSClipView object (actually an instance of a private class WebClipView ) managed by a WebView through subclassing. 我们不能通过子类化WebClipViewWebView管理的NSClipView对象(实际上是私有类WebClipView的实例)。 Instead, we can use a technique called method swizzling . 相反,我们可以使用一种称为方法调配的技术。

In the @implementation of your AppDelegate class, add AppDelegate类的@implementation中,添加

static BOOL (*kOriginalScrollTo)(id, SEL, const CGPoint *, NSInteger, NSUInteger);

static BOOL scrollTo_override(id self, SEL _cmd, const CGPoint *pointRef, NSInteger animationSpecifier, NSUInteger knobFlashSpecifier)
{
    return kOriginalScrollTo(self, _cmd, pointRef, 2, knobFlashSpecifier);
}

+ (void)load
{
    SEL selector = @selector(_scrollTo:animateScroll:flashScrollerKnobs:);
    id WebClipViewClass = objc_getClass("WebClipView");
    Method originalMethod = class_getInstanceMethod(WebClipViewClass, selector);
    kOriginalScrollTo = (void *)method_getImplementation(originalMethod);
    if(!class_addMethod(WebClipViewClass, selector, (IMP)scrollTo_override, method_getTypeEncoding(originalMethod))) {
        method_setImplementation(originalMethod, (IMP)scrollTo_override);
    }
}

You can read more about what's happening here in Mike Ash's article, “Method Replacement for Fun and Profit” ; 你可以在Mike Ash的文章“乐趣和利润的方法替换”中阅读更多关于这里发生的事情的内容; I'm using “Direct Override” method swizzling. 我正在使用“直接覆盖”方法调配。

As a result of this code, scrollTo_override() will be called instead of the WebClipView method -[_scrollTo:animateScroll:flashScrollerKnobs:] . 作为此代码的结果,将调用scrollTo_override()而不是WebClipView方法-[_scrollTo:animateScroll:flashScrollerKnobs:] All scrollTo_override() does is call the original -[_scrollTo:animateScroll:flashScrollerKnobs:] with 2 as the animationSpecifier . 所有scrollTo_override()都调用原始的-[_scrollTo:animateScroll:flashScrollerKnobs:]其中2为animationSpecifier This seems to prevent scroll animation from occurring. 这似乎阻止了滚动动画的发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM