出现键盘时调整 IOS WKWebView 的大小 [英] Resize IOS WKWebView when keyboard appears

查看:91
本文介绍了出现键盘时调整 IOS WKWebView 的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想调整 WKWebView 的大小以适合横向和纵向的键盘上方,并在使用键盘时应对用户在横向和纵向之间的切换.我还希望在键盘消失时调整 WKWebView 的大小.

I would like to resize a WKWebView to fit above the keyboard in both landscape and portrait and to cope with user changing between landscape and portrait whilst the keyboard is in use. I would also like the WKWebView to be resized when the keyboard disappears.

默认行为是滚动 WKWebView,以便使用中的文本字段在键盘上方可见.我想覆盖此行为.

The default behaviour is to scroll the WKWebView so that the text field in use is visible above the keyboard. I want to override this behaviour.

我希望我必须添加一些代码来响应 keyboardDidShow 和 keyboardDidHide,以更改 WebView 使用的 GCRect.这些是要使用的正确事件吗?

I expect that I will have to add some code to respond to keyboardDidShow and to keyboardDidHide, to change the GCRect used by the WebView. Are these the correct events to use?

如何在纵向和横向模式下访问键盘的高度?

How do I access the height of the keyboard in both portrait and landscape?

我是否必须为此添加延迟,还是在 keyboardDidShow 触发时 Web 视图的默认滚动已经发生?

Do I have to add a delay to this, or will the default scrolling of the webview have already occurred by the time keyboardDidShow fires?

当我改变 webview GCRect 大小时,这会触发 javascript 中的 window.onresize 吗?

When I change the webview GCRect size, will this trigger window.onresize in the javascript?

这样做会允许在使用键盘时旋转设备还是我需要添加更多代码来处理这个问题?

Will doing this allow the device to be rotated whilst the keyboard is in use or do I need to add further code to handle this?

感谢任何人能给我的任何帮助.

Thanks for any help anyone can give me.

推荐答案

为了解决这个问题,我在 ViewController.h 中添加了以下声明

To solve this I added the following declarations to 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 对象的属性,但这与答案无关

I expect that I should have declared these as properties of my ViewController object, but that is noting to do with the answer

然后我按如下方式创建网络视图

I then create the web view as follows

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

然后我对尺寸的变化做出如下反应

I then react to changes in size as follows

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

我也注册了键盘事件通知如下

I also register for notification of keyboard events as follows

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

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

并以这种方式对这些做出反应

And react to these in this way

- (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 函数

In the above sections I have referred to two Javascript functions

IOSOrientationChanged 根据在 window.innerWidth 和 window.innerHeight 中找到的屏幕大小重绘应用内容.

IOSOrientationChanged redraws the app content based on the size of the screen found in window.innerWidth and window.innerHeight.

IOSKeyboard Changed 做了同样的事情,但使用 window.innerHeight 减去键盘的高度(作为唯一参数传递给它).

IOSKeyboard Changed does the same but uses window.innerHeight less the height of the keyboard (which is passed as the only parameter to it).

注意事项

  1. 不要在 javascript 中对 window.onorientationchange 或 window.onresize 做出反应
  2. 我在旋转时为 web 视图创建了一个新框架,但通过在转换期间执行此操作,然后在完成时调用 javascript 代码,这对我来说已经足够了.
  3. 我最初尝试在完成时创建一个新框架,但这给我带来了许多问题,因为这花费了几毫秒,并且需要在 javascript 中添加可变延迟以等待它发生.
  4. 我还尝试将新框架的创建移动到旋转之前,但这导致了启动屏幕问题.上面没有显示,我在视图控制器中有一个与我的启动屏幕相同的视图,它显示在 viewDidLoad 上以涵盖加载 html/css/javascript 所花费的时间.当 javascript 报告它已加载时,它会被删除.
  5. 当键盘出现或移除时,我不需要创建新框架,我只是通知 javascript 不要使用隐藏区域.我发现在此处创建新的 Web 视图框架具有与上述相同的时间延迟问题.
  6. 请注意,此解决方案适用于在键盘可见的情况下旋转设备.

更新 IOS 13.3.1

UPDATE IOS 13.3.1

更新到这个版本后,我发现上面的代码不足以防止web view偶尔滚动部分看不到.请注意偶尔".大部分时间代码都像以前一样工作,但是偶尔出现的问题足以保证修复,为此我执行了以下操作:

After updating to this version, I found that the code above was insufficient to prevent the web view occasionally scrolling partially out of sight. Please note the "occasionally". Most of the time the code worked as it did previously, however the occasional issues were sufficient to warrant a fix and to do this I did the following :

  1. 添加到ViewController接口声明

  1. add to the ViewController interface statement

UIScrollViewDelegate

UIScrollViewDelegate

在创建 Web 视图后添加以下行

after creating the web view add the following line

webView.scrollView.delegate = self;

webView.scrollView.delegate = self ;

也添加

  • (void)scrollViewDidScroll:(UIScrollView *)scrollView

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

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

这篇关于出现键盘时调整 IOS WKWebView 的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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