簡體   English   中英

出現鍵盤時調整 IOS WKWebView 的大小

[英]Resize IOS WKWebView when keyboard appears

我想調整 WKWebView 的大小以適應橫向和縱向的鍵盤上方,並在使用鍵盤時應對用戶在橫向和縱向之間的切換。 我還希望在鍵盤消失時調整 WKWebView 的大小。

默認行為是滾動 WKWebView,以便使用的文本字段在鍵盤上方可見。 我想覆蓋這種行為。

我希望我必須添加一些代碼來響應keyboardDidShow 和keyboardDidHide,以更改WebView 使用的GCRect。 這些是要使用的正確事件嗎?

如何訪問縱向和橫向鍵盤的高度?

我是否必須為此添加延遲,或者在keyboardDidShow 觸發時webview 的默認滾動是否已經發生?

當我更改 webview GCRect 大小時,這會觸發 javascript 中的 window.onresize 嗎?

這樣做是否允許在使用鍵盤時旋轉設備,還是我需要添加更多代碼來處理這個問題?

感謝任何人都可以給我的任何幫助。

為了解決這個問題,我將以下聲明添加到 ViewController.h

int appH ; // device width
int appW ; // device height
int keyH ; // keyboard height
int topMargin ; // safe area size at top of screen
int bottomMargin ; // safe area size at bottom of screen
bool smallScreen ; // whether want to see status bar in landscape

我希望我應該將這些聲明為我的 ViewController object 的屬性,但這與答案有關

然后我創建 web 視圖如下

- (void)viewDidAppear:(BOOL)animated
    {
    [super viewDidAppear:(BOOL)animated];

    NSString *deviceType = [UIDevice currentDevice].model;
    smallScreen = [deviceType hasPrefix:@"iPhone"];

    WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init];
    [theConfiguration.userContentController addScriptMessageHandler:self name:@"MyApp"];
    [theConfiguration.preferences setValue:@"TRUE" forKey:@"allowFileAccessFromFileURLs"];

    // note that in viewDidLoad safeAreaInsets is set to zero
    topMargin = [UIApplication sharedApplication].statusBarFrame.size.height ;
    if (@available(iOS 11, *)) topMargin = self.view.safeAreaInsets.top ;
    bottomMargin = 0 ;
    if (@available(iOS 11, *)) bottomMargin = self.view.safeAreaInsets.bottom ;

    int top    = (smallScreen && appW > appH)? 0    : topMargin ;
    int height = (smallScreen && appW > appH)? appH : appH - topMargin - bottomMargin ;

    webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, top , appW, height) configuration:theConfiguration];
    webView.navigationDelegate = self;
    webView.UIDelegate = self;

然后我對大小的變化做出如下反應

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
    {
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    // code here executes before rotation
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
        {
        // code here executes during rotation
        appH = size.height ;
        appW = size.width  ;
        int top    = (smallScreen && appW > appH)? 0    : topMargin ;
        int height = (smallScreen && appW > appH)? appH : appH - topMargin - bottomMargin ;
        webView.frame = CGRectMake(0, top , appW, height);
        }
     completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
        {
        // code here executes after rotation
        [webView evaluateJavaScript:@"IOSOrientationChanged()" completionHandler:nil];
        }
     ];
    }

我還注冊鍵盤事件通知如下

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                                selector:@selector(keyboardWillHide:)
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];

並以這種方式對這些做出反應

- (void)keyboardWillShow: (NSNotification *) notif
    {
    keyH = [notif.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height ;
    NSString *javascriptString ;
    javascriptString = [NSString stringWithFormat:@"IOSKeyboardChanged(%d)",keyH];
    [webView evaluateJavaScript:javascriptString completionHandler:nil];
    }

- (void)keyboardWillHide: (NSNotification *) notif
    {
    [webView evaluateJavaScript:@"IOSKeyboardChanged(0)" completionHandler:nil];
    }

在上面的部分中,我提到了兩個 Javascript 函數

IOSOrientationChanged 根據 window.innerWidth 和 window.innerHeight 中找到的屏幕尺寸重繪應用內容。

IOSKeyboard Changed 的作用相同,但使用 window.innerHeight 減去鍵盤的高度(作為唯一參數傳遞給它)。

注意事項

  1. 不要在 javascript 中對 window.onorientationchange 或 window.onresize 做出反應
  2. 我為旋轉時的 web 視圖創建了一個新框架,但是通過在過渡期間執行此操作,然后在完成時調用 javascript 代碼,這對我來說已經足夠了。
  3. 我最初嘗試在完成時創建一個新幀,但這給我帶來了很多問題,因為這需要幾毫秒,並且需要在 javascript 中添加可變延遲以等待它發生。
  4. 我還嘗試將新框架創建移動到旋轉之前,但這會導致啟動屏幕問題。 上面未顯示,我有一個內部視圖 controller 與我的啟動屏幕相同,該屏幕顯示在 viewDidLoad 上,以涵蓋加載 html/css/javascript 所花費的時間。 當 javascript 報告它已被加載時,這將被刪除。
  5. 當鍵盤出現或移除時,我不需要創建新框架,我只是通知 javascript 不要使用隱藏區域。 我發現在這里創建新的 web 視圖框架具有與上述相同的時間延遲問題。
  6. 請注意,當使用鍵盤旋轉設備可見時,此解決方案有效。

更新 IOS 13.3.1

更新到這個版本后,我發現上面的代碼不足以防止 web 視圖偶爾滾動部分看不見。 請注意“偶爾”。 大多數時候代碼都像以前一樣工作,但是偶爾出現的問題足以保證修復,為此我做了以下操作:

  1. 添加到 ViewController 接口語句

    UIScrollViewDelegate

  2. 創建 web 視圖后添加以下行

    webView.scrollView.delegate = self;

  3. 還添加

    • (void)scrollViewDidScroll:(UIScrollView *)scrollView

    { [scrollView setContentOffset:CGPointMake(0,0)]; };

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM