2012-07-17 61 views
3

我在可編輯的webView中顯示了一些文本。只要我向下滾動並觸摸某處來編輯呈現的文本,它就會自動滾動到頂部並出現鍵盤,因此我必須再次將其向下滾動以進行編輯。有沒有辦法阻止webView做到這一點?可編輯的webView自動滾動到頂部

回答

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]; 
    ... 
} 

你的Wi之後會需要處理事件表現出鍵盤的時候:

- (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.

+0

非常感謝這麼全面的回答。我很感激。該解決方案確實在一定程度上解決了問題。關於「光標不在可見區域時編輯文本」問題,我使用以下兩個函數在textView中解決了這個問題。儘管我也必須在webView中嘗試它們。 – gamersoul 2012-07-19 05:02:49

+0

謝爾蓋,你是對的。肯定會死的。 – velkopopovizky 2012-07-19 10:12:45

+0

謝爾蓋,你寫過那個教程了嗎? :)我一直在努力與這些'UIWebView's很長一段時間。 – 2012-09-25 23:03:06

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]; 




} 
0

實際上keyboardWasShown不會總是特別是當用戶已經BT鍵盤連接和虛擬一個可以隱藏/通過彈出鍵所示調用。我們已經實現了自己的類,如:

@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 

希望這將幫助任何人誰是關心處理鍵盤的存在屏幕上。

4

工作得很好的方法是在鍵盤顯示時臨時禁用UIScrollView上的setContentOffset:。儘管這有點不妥,但在某些情況下,它可能會導致其他問題。

正如@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{ 

} 

這樣可以防止web視圖從擺在首位滾動到頂部,這樣就不會顯示不錯的動畫,但是,在一些situatio ns可能會導致一些問題(例如,在擁有webview的視圖中有更多的輸入控件)。在iOS 5.0+中成功測試了這一點。 在iOS 6.0中,滾動到頂部似乎是固定的,因此沒有必要解決方法。

+0

謝謝你!奇蹟般有效! ^^它可以在4.3模擬器上運行。像這個解決方案更好,因爲它消除了屏幕碰撞。對於想要完全控制其頁面的phonegap開發人員非常有用 – Arthur 2013-03-07 12:37:12