[javascript] iPad Web App : Safari에서 JavaScript를 사용하여 가상 키보드 감지?

iPad 용 웹 앱을 작성하고 있습니다 ( 일반 App Store 앱이 아니라 HTML, CSS 및 JavaScript를 사용하여 작성되었습니다). 키보드가 화면의 많은 부분을 차지하므로 키보드가 표시 될 때 남은 공간에 맞게 앱의 레이아웃을 변경하는 것이 좋습니다. 그러나 키보드가 표시되는지 여부를 감지하는 방법을 찾지 못했습니다.

첫 번째 아이디어는 텍스트 필드에 포커스가있을 때 키보드가 표시되는 것으로 가정했습니다. 그러나 외부 키보드가 iPad에 연결되어 있으면 텍스트 필드에 포커스가있을 때 가상 키보드가 표시되지 않습니다.

내 실험에서 키보드는 DOM 요소의 높이 또는 스크롤 높이에 영향을 미치지 않았으며 키보드가 표시되는지 여부를 나타내는 독점 이벤트 또는 속성을 찾지 못했습니다.



답변

조금 추악하지만 작동하는 솔루션을 찾았습니다. 모든 상황에서 작동하지는 않지만 나에게 효과적입니다. 사용자 인터페이스의 크기를 iPad의 창 크기에 맞추기 때문에 사용자는 일반적으로 스크롤 할 수 없습니다. 즉, 창의 scrollTop을 설정하면 0으로 유지됩니다.

반면에 키보드가 표시되면 스크롤이 갑자기 작동하는 것입니다. 그래서 scrollTop을 설정하고 즉시 값을 테스트 한 다음 재설정 할 수 있습니다. 다음은 jQuery를 사용하여 코드에서 어떻게 보일 수 있는지 보여줍니다.

$(document).ready(function(){
    $('input').bind('focus',function() {
        $(window).scrollTop(10);
        var keyboard_shown = $(window).scrollTop() > 0;
        $(window).scrollTop(0);

        $('#test').append(keyboard_shown?'keyboard ':'nokeyboard ');
    });
});

일반적으로이 정보는 사용자에게 보이지 않을 것으로 예상됩니다. 불행히도, 적어도 시뮬레이터에서 실행할 때 iPad는 눈에 띄게 (빠르지 만) 위아래로 스크롤됩니다. 그러나 적어도 특정 상황에서는 작동합니다.

나는 이것을 iPad에서 테스트했으며 잘 작동하는 것 같습니다.


답변

포커스 아웃 이벤트를 사용하여 키보드 해제를 감지 할 수 있습니다 . 흐릿하지만 거품처럼 보입니다. 키보드가 닫히면 시작됩니다 (물론 다른 경우에도). Safari 및 Chrome에서 이벤트는 레거시 메소드가 아닌 addEventListener로만 등록 할 수 있습니다. 다음은 키보드 해제 후 Phonegap 앱을 복원하는 데 사용한 예입니다.

 document.addEventListener('focusout', function(e) {window.scrollTo(0, 0)});

이 스 니펫이 없으면 앱 컨테이너는 페이지를 새로 고칠 때까지 위로 스크롤 된 위치에있었습니다.


답변

어쩌면 약간 더 나은 해결책은 다양한 입력 필드에서 “blur”이벤트를 바인딩하는 것입니다 (제 경우에는 jQuery 사용).

키보드가 사라지면 모든 양식 필드가 흐리게 표시되기 때문입니다. 그래서 내 상황 에서이 문제는 해결되었습니다.

$('input, textarea').bind('blur', function(e) {

       // Keyboard disappeared
       window.scrollTo(0, 1);

});

도움이되기를 바랍니다. 미셸


답변

화상 키보드가있는 경우, 뷰포트 하단 근처에있는 텍스트 필드에 초점을 맞추면 Safari가 텍스트 필드를 스크롤하여 스크롤합니다. 이 현상을 악용하여 키보드의 존재를 감지하는 방법이있을 수 있습니다 (페이지 하단에 작은 텍스트 필드가있어 순간적으로 초점을 얻거나 이와 유사한 것).


답변

포커스 이벤트 중에 문서 높이를 지나서 마술처럼 창을 스크롤 할 수 있습니다. 가상 높이는 innerHeight만큼 줄어 듭니다. 가상 키보드의 크기는 가로 방향과 세로 방향에 따라 다르므로 변경시 다시 감지해야합니다. 사용자가 언제든지 블루투스 키보드를 연결 / 연결 해제 할 수 있으므로 이러한 값을 기억하지 않는 것이 좋습니다.

var element = document.getElementById("element"); // the input field
var focused = false;

var virtualKeyboardHeight = function () {
    var sx = document.body.scrollLeft, sy = document.body.scrollTop;
    var naturalHeight = window.innerHeight;
    window.scrollTo(sx, document.body.scrollHeight);
    var keyboardHeight = naturalHeight - window.innerHeight;
    window.scrollTo(sx, sy);
    return keyboardHeight;
};

element.onfocus = function () {
    focused = true;
    setTimeout(function() { 
        element.value = "keyboardHeight = " + virtualKeyboardHeight() 
    }, 1); // to allow for orientation scrolling
};

window.onresize = function () {
    if (focused) {
        element.value = "keyboardHeight = " + virtualKeyboardHeight();
    }
};

element.onblur = function () {
    focused = false;
};

사용자가 블루투스 키보드를 사용하는 경우 keyboardHeight는 44이고 [이전] [다음] 도구 모음의 높이입니다.

이 감지를 할 때 약간의 깜박임이 있지만 피할 수는 없습니다.


답변

편집 : 실제로 작동하지는 않지만 Apple에서 문서화 : 키보드 표시를 통한 WKWebView 동작 : “iOS 10에서 WKWebView 객체는 키보드가 표시되고 호출되지 않는 경우 window.innerHeight 속성을 업데이트하여 Safari의 기본 동작과 일치합니다. 이벤트 크기 조정 “(아마도 크기 조정 대신 초점 또는 초점 + 지연을 사용하여 키보드 감지)

편집 : 코드는 외부 키보드가 아닌 화면 키보드를 가정합니다. 정보는 온 스크린 키보드에만 관심이있는 다른 사람에게 유용 할 수 있으므로 그대로 두십시오. 페이지 매개 변수를 보려면 http://jsbin.com/AbimiQup/4 를 사용하십시오 .

document.activeElement키보드가 입력 요소 인지 확인합니다 (입력 유형 = 텍스트, 텍스트 영역 등).

다음 코드는 우리의 목적을 위해 퍼지합니다 (일반적으로 정확하지는 않지만).

function getViewport() {
    if (window.visualViewport && /Android/.test(navigator.userAgent)) {
        // https://developers.google.com/web/updates/2017/09/visual-viewport-api    Note on desktop Chrome the viewport subtracts scrollbar widths so is not same as window.innerWidth/innerHeight
        return {
            left: visualViewport.pageLeft,
            top: visualViewport.pageTop,
            width: visualViewport.width,
            height: visualViewport.height
        };
    }
    var viewport = {
            left: window.pageXOffset,   // http://www.quirksmode.org/mobile/tableViewport.html
            top: window.pageYOffset,
            width: window.innerWidth || documentElement.clientWidth,
            height: window.innerHeight || documentElement.clientHeight
    };
    if (/iPod|iPhone|iPad/.test(navigator.platform) && isInput(document.activeElement)) {       // iOS *lies* about viewport size when keyboard is visible. See http://stackoverflow.com/questions/2593139/ipad-web-app-detect-virtual-keyboard-using-javascript-in-safari Input focus/blur can indicate, also scrollTop: 
        return {
            left: viewport.left,
            top: viewport.top,
            width: viewport.width,
            height: viewport.height * (viewport.height > viewport.width ? 0.66 : 0.45)  // Fudge factor to allow for keyboard on iPad
        };
    }
    return viewport;
}


function isInput(el) {
    var tagName = el && el.tagName && el.tagName.toLowerCase();
    return (tagName == 'input' && el.type != 'button' && el.type != 'radio' && el.type != 'checkbox') || (tagName == 'textarea');
};

위의 코드는 대략적인 것입니다 : 스플릿 키보드, 도킹되지 않은 키보드, 물리적 키보드에는 잘못되었습니다. 상단의 주석에 따라 window.innerHeight속성을 사용하여 Safari (iOS8 이후) 또는 WKWebView (iOS10 이후)의 주어진 코드보다 더 나은 작업을 수행 할 수 있습니다 .

다른 상황에서 실패를 발견했습니다. 예 : 입력에 초점을 맞춘 다음 홈 화면으로 이동 한 다음 페이지로 돌아옵니다. iPad는 뷰포트를 작게 만들지 않아야합니다. 이전 IE 브라우저는 작동하지 않습니다. Opera는 키보드를 닫은 후에도 요소에 계속 집중했기 때문에 작동하지 않았습니다.

그러나 뷰포트를 확대 / 축소하거나 환경 설정에서 강제 확대를 사용하도록 설정 한 경우 태그가있는 답변 (높이를 측정하기 위해 스크롤 탑을 변경)에 UI 부작용이 발생합니다. iOS에서 뷰포트가 확대 가능하고 포커스 된 입력으로 스크롤 할 때 스크롤링 및 줌 및 포커스 사이에 버그가있는 상호 작용이 있기 때문에 다른 제안 된 솔루션 (스크롤 탑 변경)을 사용하지 않습니다. 명백한).


답변

Android 4.1.1에서만 테스트되었습니다.

블러 이벤트는 키보드를 명시 적으로 숨기는 옵션으로 키보드를 표시하는 필드에서 블러 이벤트를 트리거하지 않는 옵션으로 사용자가 키보드를 위아래로 테스트하는 신뢰할 수있는 이벤트가 아닙니다.

그러나 크기 조정 이벤트는 어떤 이유로 키보드가 올라가거나 내려 오는 경우 매력처럼 작동합니다.

커피:

$(window).bind "resize", (event) ->  alert "resize"

어떤 이유로 든 키보드가 표시되거나 숨겨 질 때마다 발생합니다.

그러나 안드로이드 브라우저 (앱이 아닌)의 경우 철회 가능한 URL 표시 줄이있어 철회 할 때 크기가 조정되지 않지만 사용 가능한 창 크기가 변경됩니다.