2017-12-16 18 views
1

私はこの問題に対して洗練された回避策を講じており、他のユーザーが既により堅牢なソリューションを提供していることを期待しています。タッチスクリーン上タッチスクリーンデバイス上の仮想キーボードの開閉を検出する


、編集可能なテキストフィールドをタップすると、オンスクリーンキーボードが表示されますが、これは利用可能な画面スペースの量を変更します。未処理のままにしておくと、重要な要素が隠されたり、フッターが外れたりすることがあります。

ラップトップコンピュータまたはデスクトップコンピュータで、編集可能なテキストフィールドを開くと、そのようなレイアウト変更は作成されません。

現在のプロジェクトでは、仮想キーボードが開いていても特定のキーアイテムが表示されるようにしたいので、そのような変更がいつ発生するのかを検出する必要があります。その後、キーボードの存在に合わせてレイアウトを変更するために、body要素にクラスを追加できます。 、あなたのコードは、タッチスクリーンを持っている非モバイルデバイスがあり、モバイルデバイス

  • 上で実行されていることを知るのない完璧な方法はありません

    1. :オンライン既存のソリューションを探し

      とき、私はことを発見しましたまた、キーボードは

    2. 焦点要素が
    3. contentEditable要素は、オンスクリーンキーボード
    4. アドレスバーを開きます編集可能ではないかもしれない持っている可能性があります仮想キーボードが現れると同時に、必要な画面スペースを再表示して使用することを決定し、使用可能なスペースをさらに絞ることができます。

    私が下に出てきた解決策を掲載しました。これは、キーボードのフォーカス変更の1秒以内にウィンドウの高さの変化を検出することに依存しています。私は、クロスプラットフォーム、クロスブラウザ、および複数のデバイスでテストされたより良いソリューションを提案したいと考えています。


    私はrepository on GitHubを作成しました。
    私のソリューションhereをテストすることができます。

    私のテストでは、ユーザーがタッチスクリーンとキーボードとマウスを備えたコンピュータを使用していて、編集可能な要素を最初にマウスで選択してすぐにウィンドウを変更すると、高さ。コンピュータやモバイルデバイスで、他の誤検出やネガティブなものが見つかった場合は、教えてください。キーボードの開口部を検出する直接的な方法として


    ;(function(){ 
    
        class Keyboard { 
        constructor() { 
         this.screenWidth = screen.width  // detect orientation 
         this.windowHeight = window.innerHeight // detect keyboard change 
         this.listeners = { 
         resize: [] 
         , keyboardchange: [] 
         , focuschange: [] 
         } 
    
         this.isTouchScreen = 'ontouchstart' in document.documentElement 
    
         this.focusElement = null 
         this.changeFocusTime = new Date().getTime() 
         this.focusDelay = 1000 // at least 600 ms is required 
    
         let focuschange = this.focuschange.bind(this) 
         document.addEventListener("focus", focuschange, true) 
         document.addEventListener("blur", focuschange, true) 
    
         window.onresize = this.resizeWindow.bind(this) 
        } 
    
        focuschange(event) { 
         let target = event.target 
         let elementType = null 
         let checkType = false 
         let checkEnabled = false 
         let checkEditable = true 
    
         if (event.type === "focus") { 
         elementType = target.nodeName 
         this.focusElement = target 
    
         switch (elementType) { 
          case "INPUT": 
          checkType = true 
          case "TEXTAREA": 
          checkEditable = false 
          checkEnabled = true 
          break 
         } 
    
         if (checkType) { 
          let type = target.type 
          switch (type) { 
          case "color": 
          case "checkbox": 
          case "radio": 
          case "date": 
          case "file": 
          case "month": 
          case "time": 
           this.focusElement = null 
           checkEnabled = false 
          default: 
           elementType += "[type=" + type +"]" 
          } 
         } 
    
         if (checkEnabled) { 
          if (target.disabled) { 
          elementType += " (disabled)" 
          this.focusElement = null 
          } 
         } 
    
         if (checkEditable) { 
          if (!target.contentEditable) { 
          elementType = null 
          this.focusElement = null 
          } 
         } 
         } else { 
         this.focusElement = null 
         } 
    
         this.changeFocusTime = new Date().getTime() 
    
         this.listeners.focuschange.forEach(listener => { 
         listener(this.focusElement, elementType) 
         }) 
        } 
    
        resizeWindow() { 
         let screenWidth = screen.width; 
         let windowHeight = window.innerHeight 
         let dimensions = { 
         width: innerWidth 
         , height: windowHeight 
         } 
         let orientation = (screenWidth > screen.height) 
             ? "landscape" 
             : "portrait" 
    
         let focusAge = new Date().getTime() - this.changeFocusTime 
         let closed = !this.focusElement 
           && (focusAge < this.focusDelay)    
           && (this.windowHeight < windowHeight) 
         let opened = this.focusElement 
           && (focusAge < this.focusDelay) 
           && (this.windowHeight > windowHeight) 
    
         if ((this.screenWidth === screenWidth) && this.isTouchScreen) { 
         // No change of orientation 
    
         // opened or closed can only be true if height has changed. 
         // 
         // Edge case 
         // * Will give a false positive for keyboard change. 
         // * The user has a tablet computer with both screen and 
         // keyboard, and has just clicked into or out of an 
         // editable area, and also changed the window height in 
         // the appropriate direction, all with the mouse. 
    
         if (opened) { 
          this.keyboardchange("shown", dimensions) 
         } else if (closed) { 
          this.keyboardchange("hidden", dimensions) 
         } else { 
          // Assume this is a desktop touchscreen computer with 
          // resizable windows 
          this.resize(dimensions, orientation) 
         } 
    
         } else { 
         // Orientation has changed 
         this.resize(dimensions, orientation) 
         } 
    
         this.windowHeight = windowHeight 
         this.screenWidth = screenWidth 
        } 
    
        keyboardchange(change, dimensions) { 
         this.listeners.keyboardchange.forEach(listener => { 
         listener(change, dimensions) 
         }) 
        } 
    
        resize(dimensions, orientation) { 
         this.listeners.resize.forEach(listener => { 
         listener(dimensions, orientation) 
         }) 
        } 
    
        addEventListener(eventName, listener) { 
         // log("*addEventListener " + eventName) 
    
         let listeners = this.listeners[eventName] || [] 
         if (listeners.indexOf(listener) < 0) { 
         listeners.push(listener) 
         } 
        } 
    
        removeEventListener(eventName, listener) { 
         let listeners = this.listeners[eventName] || [] 
         let index = listeners.indexOf(listener) 
    
         if (index < 0) { 
         } else {  
         listeners.slice(index, 1) 
         } 
        } 
        } 
    
        window.keyboard = new Keyboard() 
    
    })() 
    
  • +0

    あなたは 'screen.availHeight'と' screen.availWidth'を使って画面サイズの変化を検知することができます。 [これも見つかりました](https://stackoverflow.com/questions/4745988/how-do-i-detect-if-software-keyboard-is-visible-on-android-device) –

    答えて

    0

    、あなただけの高さと幅で検出することができます。 JavaScriptのscreen.availHeightscreen.availWidth多分助けにSee more

    0

    これは「正しく」取得するのは難しい問題です。入力要素のフォーカスにフッターを表示して非表示にすることはできますが、ぼかしを表示することはできますが、iOSでは必ずしも信頼できるとは限りません。私のiPhone 4Sでは10回に1回、フォーカスイベントが発生しないようです(またはJQuery Mobileとの競合状態があるかもしれません)。フッタは隠されません。

    多くの試行錯誤の後、私はこの興味深いソリューションを思い付いた:

    基本的に
    <head> 
        ...various JS and CSS imports... 
        <script type="text/javascript"> 
         document.write('<style>#footer{visibility:hidden}@media(min-height:' + ($(window).height() - 10) + 'px){#footer{visibility:visible}}</style>'); 
        </script> 
    </head> 
    

    :その後、動的時にフッターを非表示にするCSSメディアクエリを作成し、デバイスのウィンドウの高さを決定するためにJavaScriptを使用ウィンドウの高さは10ピクセル縮小します。キーボードを開くとブラウザのディスプレイがリサイズされるため、これはiOSでは失敗しません。 JavaScriptではなくCSSエンジンを使用しているので、はるかに高速でスムーズです!

    注: 'visibility:hidden'は 'display:none'または 'position:static'よりも不安定ですが、マイレージが異なる場合があります。

    関連する問題