【问题标题】:Ionic 4 Cordova - How to fix keyboard covering input fields on Windows (Surface)Ionic 4 Cordova - 如何修复键盘覆盖 Windows 上的输入字段(Surface)
【发布时间】:2021-04-21 07:44:22
【问题描述】:

我有一个基于 Ionic 4 / Angular cordova 的应用程序(帖子末尾的 Ionic 信息)。

由于this issue,我目前正在使用Cordova windows 6.0.1。一切似乎都很好,除了这个问题是关于什么的。

当我在 Windows Surface 平板电脑上选择输入字段时,键盘会覆盖输入字段,即应用程序不会像在 iOSAndroid 上那样降低它的高度(它在其他两个平台上运行良好)。

当我查看正在运行的 Android 设备(使用 chrome://inspect)上发生的情况时,我注意到带有选择器 ion-appmd ion-page hydrated 的元素的高度从 616px 减少到 325px

我还没有找到在远程 Windows 设备上进行相同调试的方法,所以我无法对此进行调查,但我认为上述情况并未发生。

我发现this post 对我来说很有意义,因为它看起来正在调整ion-app 的高度。我已经复制了该代码(删除了jquery),但我的问题是keyboardDidShow 事件在我调用表面上的键盘时似乎没有触发(我有日志记录我发送到服务器所以我可以看到这没有发生)。

所以我的(类似)代码如下...

  const ionApp = document.getElementsByTagName("ion-app")[0];
  this.logger.info(ionApp ? "got app" : "not got app");

  window.addEventListener('keyboardDidShow', async (event) => {        
    this.logger.info('keyboardDidShow'); // <----- don't even get to here

    // Move ion-app up, to give room for keyboard
    let kbHeight: number = event["keyboardHeight"];
    let viewportHeight: number = window.innerHeight;

    this.logger.info(`viewportHeight: ${viewportHeight}`);

    const focusedElement = document.activeElement;
    if (!focusedElement) {
      this.logger.warn('windowsKeyboardWorkaround: Could not get focused input');
      return;
    }

    let inputFieldOffsetFromBottomViewPort: number = viewportHeight - focusedElement.getBoundingClientRect().bottom;
    let inputScrollPixels = kbHeight - inputFieldOffsetFromBottomViewPort;

    // Set margin to give space for native keyboard.
    ionApp.style["margin-bottom"] = kbHeight.toString() + "px";

    // But this diminishes ion-content and may hide the input field...
    if (inputScrollPixels > 0) {
      const content = document.getElementsByTagName('ion-content');
      if (!content || content.length == 0)
        return;

      const topMostContent = content[content.length - 1];
      let ionScroll = await topMostContent.getScrollElement();

       setTimeout(() => {
         ionScroll.animate({
          scrollTop: ionScroll.scrollTop + inputScrollPixels
        }, 300);
      }, 300); // Matches scroll animation from css.         
    }
  });
  window.addEventListener('keyboardDidHide', () => {
    // Move ion-app down again
    // Scroll not necessary.
    ionApp.style["margin-bottom"] = "0px";
  });

是否有人对此事件有任何想法,以及为什么它没有为我触发,或者是否有办法查看窗口(或其他)上的所有事件以查看是否有键盘事件被引发?

提前感谢您提供任何信息。

[更新1]

我在 Android 上运行时忘记删除此代码,我注意到这里提出了keyboardDidShow IS(即在 Android 上,我当然不需要它)。所以它似乎只是在 Windows 上,或者至少是我必须测试的 Surface 平板电脑。

[更新2]

看起来keyboardDidHide 事件来自cordova keyboard plugin,其中表示仅支持 iOS 和 Android。果然,如果我们去source,我只看到iosandroid...

所以我需要其他方法...

[更新3]

在我的应用程序的其他地方,我使用以下命令隐藏了 WINdows 后退按钮....

 let w: any = window;
 if (w.cordova != undefined && w.cordova.platformId == "windows") {
    let currentView = w.Windows.UI.Core.SystemNavigationManager.getForCurrentView();
    currentView.appViewBackButtonVisibility = w.Windows.UI.Core.AppViewBackButtonVisibility.collapsed;
  }

所以这意味着我们可以访问Windows.UI.Core,我假设this namespace 中的所有内容。

到目前为止,我看不到任何可以挂接到键盘显示/隐藏中的内容。

hereWindows-universal-samples\Samples\TouchKeyboard\cs 下的UWP 示例中,我在Scenario2_ShowHideEvents.xaml.cs 中看到以下内容...

 protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        InputPane currentInputPane = InputPane.GetForCurrentView();

        // Subscribe to Showing/Hiding events
        currentInputPane.Showing += OnShowing;
        currentInputPane.Hiding += OnHiding;
    }

但不知道从Windows.UI.Core.. 那里得到这个。

离子信息

    Ionic:

       Ionic CLI                     : 5.2.3 (C:\Users\peter\AppData\Roaming\npm\node_modules\ionic)
       Ionic Framework               : @ionic/angular 4.11.3
       @angular-devkit/build-angular : 0.802.0
       @angular-devkit/schematics    : 8.2.0
       @angular/cli                  : 8.2.0
       @ionic/angular-toolkit        : 2.0.0

    Cordova:

       Cordova CLI       : 9.0.0 (cordova-lib@9.0.1)
       Cordova Platforms : android 8.1.0, windows 6.0.1
       Cordova Plugins   : cordova-plugin-ionic-keyboard 2.1.3, cordova-plugin-ionic-webview 4.1.3, (and 12 other plugins)

    Utility:

       cordova-res : 0.7.0-testing.0
       native-run  : 0.2.8

    System:

       Android SDK Tools : 26.1.1 (C:\Users\peter\AppData\Local\Android\sdk)
       NodeJS            : v10.15.3 (C:\Program Files\nodejs\node.exe)
       npm               : 6.4.1
       OS                : Windows 10

【问题讨论】:

    标签: angular cordova ionic-framework uwp


    【解决方案1】:

    我刚从这种情况中走出来。

    在 app.component.ts - 平台准备好后尝试添加这个

    this.statusBar.overlaysWebView(false)
    this.statusBar.styleDefault();
    

    【讨论】:

    • 感谢您的建议,但不幸的是(对我而言)表面上仍然行不通。您使用的是运行 Windows 10 的 Windows Surface 平板电脑(在平板电脑模式下使用软键盘)吗?
    • 嗯。不,我已经在安卓智能手机上测试过了。到时候就很难找到解决办法了。
    • 好的,在 iOS 和 Android 上是的,这已经对我有用,无需做任何事情。那里只是 Windows 似乎不起作用。它正在做某事,因为当您输入输入字段时键盘会弹出 - 它只是不会将输入字段滚动到视图中。
    【解决方案2】:

    我想出了一个解决方案,虽然不是 100% 完美,因为它没有得到准确的键盘高度。我只是将视口分成两半,但总比没有好。

    我将粘贴我的整个课程(这两个 util 助手很容易弄清楚他们在做什么)

        import { Injectable } from '@angular/core';
        import { Utils } from '@shared/utils';
        import { Logger } from './logger.service';
    
        /**
         * Manages the Windows soft keyboard showing / hiding and resizing the app when it is shown/hidden
         */
        @Injectable()
        export class WindowsKeyboardService {
            /**
             * Construction
             * @param logger - logger
             */
            constructor(private logger: Logger) { }
    
            /**
             * Call from main component once the view is visible, so we can get access to Windows Input pane
             * and hook up the soft keyboard handlers
             */
            public async hookupKeyboardHandlers() : Promise<void> {
                try {
                    this.logger.info('hookupKeyboardHandlers');
    
                    // Only need this for Windows. For ioS/Android the keyboard plugin does all this for us.
                    if (!await Utils.isWindows()) {
                        this.logger.info('WindowsKeyboardService.hookupKeyboardHandlers - not windows. Skipping');
                        return;
                    }
                    
                    let w = <any>window;
                    const inputPane = w.Windows.UI.ViewManagement.InputPane.getForCurrentView();
                    if (!inputPane) {
                        this.logger.error('WindowsKeyboardService.hookupKeyboardHandlers: could not get inputPane');
                        return;
                    }
    
                    inputPane.addEventListener('showing', _ => this.onWindowsKeyboardUp);
                    inputPane.addEventListener('hiding', _ => this.onWindowsKeyboardClose);            
                } catch (error) {
                    this.logger.error(`WindowsKeyboardService.hookupKeyboardHandlers: ${error}`)
                }
            }
         
         /**
         * Raised when a Windows soft keyboard is opened
         */
            private onWindowsKeyboardUp() : void {
                try {
                    this.logger.info("onWindowKeyboardUp");
    
                    // Just half viewportHeight for now (until can find out how to get keyboard height - if even possible)
                    let viewportHeight: number = window.innerHeight;
                    let kbHeight = viewportHeight / 2;      
                    this.logger.info(`viewportHeight: ${viewportHeight}`);
                    const focusedElement = document.activeElement;
                    if (!focusedElement) {
                        this.logger.info('WindowsKeyboardService.onWindowsKeyboardUp: Could not get focused input');
                        return;
                    }
    
                    let inputFieldOffsetFromBottomViewPort: number = viewportHeight - focusedElement.getBoundingClientRect().bottom;
                    let inputScrollPixels = kbHeight - inputFieldOffsetFromBottomViewPort;
    
                    const ionApp = document.getElementsByTagName("ion-app")[0];
                    this.logger.info(ionApp ? "got app" : "not got app");
    
                    // Set margin to give space for native keyboard.
                    ionApp.style["margin-bottom"] = kbHeight.toString() + "px";
    
                    // But this diminishes ion-content and may hide the input field...
                    if (inputScrollPixels > 0) {
                        const content = document.getElementsByTagName('ion-content');
                        if (!content || content.length == 0)
                            return;
    
                        const topMostContent = content[content.length - 1];
                        setTimeout(async () => {
                            let ionScroll = await topMostContent.getScrollElement();
                            ionScroll.animate({
                                scrollTop: ionScroll.scrollTop + inputScrollPixels
                            }, 300);
                        }, 300); // Matches scroll animation from css.         
                    }
                } catch (error) {
                    this.logger.error(`WindowsKeyboardService.onWindowKeyboardUp: ${error}`);
                }
            }
    
            /**
            * Raised when a Windows soft keyboard is closed 
            */
            private onWindowsKeyboardClose(): void {
                try {
                    this.logger.info("WindowsKeyboardService.onWindowKeyboardClose");
                    const ionApp = document.getElementsByTagName("ion-app")[0];      
                    ionApp.style["margin-bottom"] = "0";
                } catch (error) {
                    this.logger.error(`WindowsKeyboardService.onWindowKeyboardClose: ${error}`);
                }
            }
        }
    

    我将它连接到 app.component..

        public async ngAfterViewInit(): Promise<void> {
            try {
                this.logger.info('AppComponent: ngAfterViewInit');
                this.windowsKeyboardService.hookupKeyboardHandlers();
            } catch (error) {
                this.logger.error(`AppComponent: ngAfterViewInit: ${error}`);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-14
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-02
      相关资源
      最近更新 更多