3

我在可编辑的 web 视图中显示了一些文本。一旦我向下滚动并触摸某处以编辑呈现的文本,它就会滚动到顶部并出现键盘,因此我必须再次向下滚动以进行编辑。有没有办法阻止 webView 这样做?

4

4 回答 4

6

遇到同样的问题,仍在寻找这种奇怪行为的正常解决方案。我们仍然无法阻止 UIWebView 这样做,如果你在 iPad 上查看 Evernote 应用程序,你会在那里看到同样的问题,不幸的是:( 我们唯一能做的就是在显示键盘时保存 UIWebView 的 contentOffset 和如果在打开键盘后恢复。

这看起来像:

//register your controller for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) UIKeyboardDidShowNotification object:nil];

然后您将需要处理键盘通知,例如:

- (void)keyboardWillShow:(NSNotification *)aNotification {

// scroll view will scroll to beginning, but we save current offset
[_yourViewWithWebView saveOffset];
    ...
}

之后,您将需要在显示键盘时处理事件:

- (void)keyboardWasShown:(NSNotification*)aNotification{
...
// scroll view scrolled to beginning, but we restore previous offset
[_yourViewWithWebView restoreOffset];
}

因此,在包含 UIWebView 的视图中,您需要实现:

static CGPoint editableWebViewOffsetPoint;

- (void) saveOffset{
    editableWebViewOffsetPoint = yourWebView.scrollView.contentOffset;
}

- (void) restoreOffset{
    //just use animation block to have scroll animated after jumping to top and back to old position
    [UIView animateWithDuration:.2
            delay:0
            options:UIViewAnimationOptionCurveEaseIn
            animations:^{
                yourWebView.scrollView.contentOffset = editableWebViewOffsetPoint;
            }
            completion:nil];

}

希望总的来说,这将帮助您至少部分解决您的问题。

如果有人能帮助我们防止每次显示键盘时 UIWebView 滚动到顶部,我将不胜感激。

UIWebView.scrollView.scrollsToTop = NO;没有帮助。

在显示键盘之前禁用滚动并在显示键盘后启用它也不起作用。

同样在将来,当光标不在 UIWebView 的可见区域时,您将面临编辑文本的问题 - 它不会自动滚动以使光标可见。我们已经解决了这个问题,但我正在创建详细且易读的教程,说明我们如何做到这一点。如果您已经解决了这个问题,我很乐意看看您的解决方案:)

PS: http: //www.cocoanetics.com/2011/01/uiwebview-must-die/

谢谢你,谢尔盖 N。

于 2012-07-18T17:00:18.370 回答
4

一种效果很好的方法是在显示键盘时暂时setContentOffset:禁用UIScrollView。不过,这有点骇人听闻,因此在某些情况下,它可能会导致其他问题。

@Sergey N. 的回复中,注册键盘通知,但不要存储/恢复 contentOffset,而是使用这些:

- (void)keyboardWillShow:(NSNotification *)aNotification {
    [self disableMethod:@selector(setContentOffset:) onClass:[UIScrollView class]];
}
- (void)keyboardWasShown:(NSNotification *)aNotification {
    [self enableMethod:@selector(setContentOffset:) onClass:[UIScrollView class]];
}

在类的其他地方(或在另一个类中,只要你self在上面的调用中替换),放置这些:

-(void)swizzleMethod:(SEL)origSel from:(Class)origClass toMethod:(SEL)toSel from:(Class)toClass{
    Method origMethod = class_getInstanceMethod(origClass, origSel);
    Method newMethod = class_getInstanceMethod(toClass, toSel);
    method_exchangeImplementations(origMethod, newMethod);
}
-(void)disableMethod:(SEL)sel onClass:(Class)cl{
    [self swizzleMethod:sel from:cl toMethod:@selector(doNothing) from:[self class]];
}
-(void)enableMethod:(SEL)method onClass:(Class)cl{
    [self swizzleMethod:@selector(doNothing) from:[self class] toMethod:method from:cl];
}
-(void)doNothing{

}

这首先防止了 webview 滚动到顶部,因此它不会显示糟糕的动画,但是,在某些情况下它可能会导致一些问题(例如,在持有 webview 的视图中有更多的输入控件)。在 iOS 5.0+ 中成功测试了这个。在 iOS 6.0 中,滚动到顶部似乎是固定的,因此不需要解决方法。

于 2013-01-27T12:06:21.143 回答
0

“当光标不在可见区域时编辑文本”问题的功能。

- (void)keyboardWasShown:(NSNotification *)aNotification {

//if(self.navigationController.viewControllers objectAtIndex:([self.navigationController.viewControllers count]-1)==self.)
NSLog(@"keyboardshown");
if (keyboardshown)
    return;
keyboardshown=YES;
NSDictionary* userInfo = [aNotification userInfo];

CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];

CGRect newFrame = self.textView.frame;
CGRect keyboardFrame = [self.textView convertRect:keyboardEndFrame toView:nil];

newFrame.size.height -= keyboardFrame.size.height;    
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];

[UIView setAnimationDuration:0.3];
[self.textView setFrame:newFrame];
[UIView commitAnimations];



}

- (void)keyboardWasHidden:(NSNotification *)aNotification {

if (!keyboardshown)
    return;
keyboardshown=NO;

NSDictionary* userInfo = [aNotification userInfo];

CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];

CGRect newFrame = self.textView.frame;
CGRect keyboardFrame = [self.textView convertRect:keyboardEndFrame toView:nil];

newFrame.size.height += keyboardFrame.size.height;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:0.3];
self.textView.frame = newFrame;
[UIView commitAnimations];




}
于 2012-07-19T05:05:48.567 回答
0

实际上,keyboardWasShown 并不总是被调用,尤其是当用户连接了 BT 键盘并且可以通过 Eject 键隐藏/显示虚拟键盘时。我们已经实现了自己的类,例如:

    @implementation KeyboardUtils

+ (CGRect) convertRect:(CGRect)rect toView:(UIView *)view {
    UIWindow *window = [view isKindOfClass:[UIWindow class]] ? (UIWindow *) view : [view window];
    return [view convertRect:[window convertRect:rect fromWindow:nil] fromView:nil];
}

/**
 * This is working but deprecated solution
 * Based on UIKeyboardCenterBeginUserInfoKey and UIKeyboardCenterEndUserInfoKey which are deprecated since iOS 3.2
 */
+ (BOOL)checkKeyboardOnDisplayCenterBegin:(CGRect)centerBegin centerEnd:(CGRect)centerEnd{

    CGRect mainScreen = [UIApplication currentBounds];

    BOOL isKeyboardOnDisplay = CGRectContainsPoint(mainScreen, centerEnd.origin);

    [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:isKeyboardOnDisplay] forKey:@"isKeyboardOnDisplay"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    return isKeyboardOnDisplay;
}

/**
 * This method allows to verify if software keyboard is currently present on screen for the application
 * Allows to handle undocked, split states of keyboard, as well as connected Bluetooth keyboard.
 * Needed to adjust UI - scrolling and insets for editable parts of the app, as well as avoid application be beneath open keyboard
 */
+ (BOOL)checkKeyboardOnDisplayBeginFrame:(CGRect)frameBegin endFrame:(CGRect)frameEnd{
    CGRect mainScreen = [UIApplication currentBounds];
    UIView *firstView = [[(AppDelegate *)[[UIApplication sharedApplication] delegate] window].subviews objectAtIndex:0];

    CGRect convertedEndFrame = [KeyboardUtils convertRect:frameEnd toView:firstView];

    BOOL isKeyboardOnDisplay = CGRectContainsRect(mainScreen, convertedEndFrame);

    [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:isKeyboardOnDisplay] forKey:@"isKeyboardOnDisplay"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    return isKeyboardOnDisplay;
}



+ (BOOL)checkKeyboardOnDisplayFromNotification:(NSNotification *)aNotification{
    BOOL isKeyboardOnDisplay = [KeyboardUtils checkKeyboardOnDisplayBeginFrame:[[aNotification.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] 
                                                                      endFrame:[[aNotification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]];    
    return isKeyboardOnDisplay;
}

然后你可以像这样使用它:

- (void)keyboardWillChangeFrame:(NSNotification*)aNotification{
    [KeyboardUtils checkKeyboardOnDisplayFromNotification:aNotification];
}

其中keyboardWillChangeFrame 是选择器观察者:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];

通过这种方式,您将键盘的状态(如果它显示为停靠的一个并且确实出现在显示器上,并且未使用 BT 键盘)到 NSUserDefaultSettings。在侦听键盘通知或方向更改的处理程序中,您应该从默认值中检查此键值。

另外一种方法是 [UIApplication currentBounds]; 它通过使用以下类别扩展它存在于应用程序中:(.h 文件)

#import <UIKit/UIKit.h>

@interface UIApplication (AppDimensions)
+(CGSize) currentSize;
+(CGRect) currentBounds;
+(CGSize) sizeInOrientation:(UIInterfaceOrientation)orientation;
@end

.m 文件:

#import "UIApplication+AppDimensions.h"

@implementation UIApplication (AppDimensions)

+(CGSize) currentSize
{
    return [UIApplication sizeInOrientation:[UIApplication sharedApplication].statusBarOrientation];
}

+(CGRect) currentBounds{
    CGRect bounds = [UIScreen mainScreen].bounds;
    bounds.size = [UIApplication currentSize];
    return bounds;
}

+(CGSize) sizeInOrientation:(UIInterfaceOrientation)orientation
{
    CGSize size = [UIScreen mainScreen].bounds.size;
    UIApplication *application = [UIApplication sharedApplication];
    if (UIInterfaceOrientationIsLandscape(orientation))
    {
        size = CGSizeMake(size.height, size.width);
    }
    if (application.statusBarHidden == NO)
    {
        size.height -= MIN(application.statusBarFrame.size.width, application.statusBarFrame.size.height);
    }
    return size;
}

@end

希望这将帮助任何关心处理屏幕上键盘存在的人。

于 2012-10-08T13:55:55.623 回答