出现键盘时调整 IOS WKWebView 的大小

Ste*_*ker 6 keyboard ios wkwebview

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

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

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

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

我是否必须为此添加延迟,或者在 keyboardDidShow 触发时 webview 的默认滚动是否已经发生?

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

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

感谢任何人可以给我的任何帮助。

Ste*_*ker 2

为了解决这个问题,我在 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
Run Code Online (Sandbox Code Playgroud)

我希望我应该将这些声明为 ViewController 对象的属性,但这与答案无关

然后我创建网络视图如下

- (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;
Run Code Online (Sandbox Code Playgroud)

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

- (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];
        }
     ];
    }
Run Code Online (Sandbox Code Playgroud)

我还注册了键盘事件的通知,如下

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

    [[NSNotificationCenter defaultCenter] addObserver:self
                                                selector:@selector(keyboardWillHide:)
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
Run Code Online (Sandbox Code Playgroud)

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

- (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];
    }
Run Code Online (Sandbox Code Playgroud)

在上面的章节中我提到了两个 Javascript 函数

IOSOrientationChanged 根据 window.innerWidth 和 window.innerHeight 中找到的屏幕大小重新绘制应用程序内容。

IOSKeyboard Changed 执行相同的操作,但使用 window.innerHeight 减去键盘的高度(作为唯一参数传递给它)。

注意事项

  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

更新到这个版本后,我发现上面的代码不足以防止网页视图偶尔部分滚动到看不见的地方。请注意“偶尔”。大多数情况下,代码的工作方式与以前一样,但是偶尔出现的问题足以保证修复,为此,我执行了以下操作:

  1. 添加到ViewController接口语句

    UIScrollViewDelegate

  2. 创建网络视图后添加以下行

    webView.scrollView.delegate = self ;

  3. 还添加

    • (void)scrollViewDidScroll:(UIScrollView *)scrollView

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