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


147

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

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

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


1
흠, 흥미로운 문제입니다. iPad의 Safari에서 "창"객체를 반복하여 키보드 지원과 관련된 특수 객체가 있는지 확인하십시오.
David Murdoch

@David가 작동하지 않습니다. 키보드는 자바 스크립트 "창"이 아닙니다.
kennytm

2
@ 케니 어. 그러나 모든 창 개체에 온 스크린 키보드 표시와 관련된 플래그가있을 수 있습니다. 한 번의 가치가 있습니다.
David Murdoch

1
나는 그것을 시도했다. 불행히도 아무것도 찾지 못했습니다. 또한 키보드를 표시하기 전후의 3 단계 깊이에있는 모든 창 속성을 비교했습니다. 차이점은 키보드의 지표와 관련이없는 것으로 보입니다.
LKM

3
이것에 대한 새로운 대답이 있습니까 ??
fraxture

답변:


54

조금 추악하지만 작동하는 솔루션을 찾았습니다. 모든 상황에서 작동하지는 않지만 나에게 효과적입니다. 사용자 인터페이스의 크기를 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에서 테스트했으며 잘 작동하는 것 같습니다.


입력에 초점을 맞출 때 화면이 약간 위로 스크롤되는 웹 앱에 문제가 있습니다. 달리 스크롤을 비활성화했지만 여전히이 스크롤입니다. 어떤 아이디어? 감사합니다 [ stackoverflow.com/questions/6740253/…
Andrew Samuelsen

아직 시도하지 않았지만 유망한 것으로 보입니다. 잘 .scrollTop(1)작동 하지 않고 덜 명확하지 않습니까?
ThinkingStiff

1
이것은 나쁜 생각입니다 ... 키보드가 블루투스 일 수도 있고 가상이 표시되지 않을 수도 있습니다.
theSociableme

3
@ theSociableme :이 솔루션의 요점은 블루투스 키보드를 올바르게 처리하는 것입니다. 블루투스 키보드를 무시하면 필드에 포커스가 있는지 확인할 수 있으므로 가상 키보드가 표시되는지 쉽게 알 수 있습니다.
LKM

5
@fraxture : 포괄적 인 설명을 모릅니다 (연구하고 작성하면 읽고 싶습니다). 두 플랫폼은 기본 브라우저에서 온 스크린 키보드를 매우 다르게 처리합니다. Android Chrome은 키보드를위한 공간을 확보하기 위해 뷰포트 높이를 축소하므로 키보드가 표시 될 때 페이지 크기가 조정됩니다. iOS Safari는 키보드로 페이지를 오버레이하고 (페이지 크기는 동일하게 유지) 스크롤 작동 방식을 변경합니다. Safari는 모두 페이지를 뷰포트 내부에서 스크롤하고 동시에 뷰포트를 이동하여 페이지의 맨 아래가 맨 아래로 스크롤 될 때 키보드 위에 있도록합니다.
LKM

32

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

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

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


1
내 문제에 대한 최상의 해결책
Sutulustus


1
또한 키보드 열림 감지를 위해 'focusin'버전을 사용할 수 있습니다.
A.Çetin

15

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

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

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

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

});

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


이 답변에 감사드립니다. iPad Safari 키보드로 인해 텍스트 영역 커서가 텍스트 영역 외부로 이동 (오프셋)되는 문제를 해결하는 것이 유용하다는 것을 알았습니다.
kennbrodhagen

14

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


1
독창적 인 아이디어입니다. 현재 스크롤 위치를 사용하여 가상 키보드를 감지하는 비슷한 솔루션을 찾았습니다.
LKM

당신은 내 하루를 구 했어요!
aztack

11

포커스 이벤트 중에 문서 높이를 지나서 마술처럼 창을 스크롤 할 수 있습니다. 가상 높이는 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이고 [이전] [다음] 도구 모음의 높이입니다.

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


5
방금 iOS 8.2에서 이것을 시도했지만 작동하지 않습니다 ... 새로운 iOS의 어떤 단계에서 작동을 멈췄습니까?
Ming

1
나에게도 효과가 없었습니다-크기 조정이 iOS9.3에서 실행되지 않습니다
llamerr

8

편집 : 실제로 작동하지는 않지만 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에서 뷰포트가 확대 가능하고 포커스 된 입력으로 스크롤 할 때 스크롤링 및 줌 및 포커스 사이에 버그가있는 상호 작용이 있기 때문에 다른 제안 된 솔루션 (스크롤 탑 변경)을 사용하지 않습니다. 명백한).


브라우저에 따라 일부 요소가 절대적으로 배치 될 때 전체 화면 나누기를 감지하는 innerHeight가 있습니다. 전혀 신뢰할 수 없습니다.
Udo

5

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

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

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

커피:

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

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

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


키보드를 수동으로 닫을 때 흐림 이벤트가 발생하지 않으면 +1입니다. 크기 조정은 좋은 아이디어이며 Android 기기에 적합합니다.
Ankit Garg 2018 년

iPhone 5 (iOS 6.0.2) 및 iPad 3 (iOS 6.0)에서 모두 작동하는지 확인할 수 있습니다.
Diego Agulló

1
CrossBrowserTesting에서 iOS6의 Chrome 41에서 방금 테스트했습니다. 크기 조정은 가상 키보드가 나타나거나 사라져도 트리거되지 않습니다.
Dan Dascalescu 1

4

키보드를 감지하는 대신 창의 크기를 감지하십시오.

창의 높이가 줄어들고 너비가 여전히 동일하면 키보드가 켜져 있음을 의미합니다. 키보드가 꺼져있는 경우 입력 필드에 포커스가 있는지 여부를 테스트하여 추가 할 수도 있습니다.

예를 들어이 코드를 사용해보십시오.

var last_h = $(window).height(); //  store the intial height.
var last_w = $(window).width(); //  store the intial width.
var keyboard_is_on = false;
$(window).resize(function () {
    if ($("input").is(":focus")) {
        keyboard_is_on =
               ((last_w == $(window).width()) && (last_h > $(window).height()));
    }   
});     

2
iOS 8에서는 더 이상 작동하지 않는 것 같습니다. 키보드는 내용을 오버레이하며 많은 경우 처음에 초점을 맞춘 입력 필드를 가리면 내용이 아래로 스크롤됩니다.
Rick Strahl

3
창 높이는 iOS 7부터 키보드를 포함한 높이를 IOS6 창에서 반환합니다. 키보드를 열면 높이가 변경됩니다.
Michiel

1
스크롤 할 때 상단 주소 표시 줄이 화면 안팎으로 슬라이드 할 때 높이도 변경됩니다. 200px (테스트되지 않음)의 최소 높이 변경을 추가해야합니다.
oriadam

1

이 솔루션은 스크롤 위치를 기억합니다

    var currentscroll = 0;

    $('input').bind('focus',function() {
        currentscroll = $(window).scrollTop();
    });

    $('input').bind('blur',function() {
        if(currentscroll != $(window).scrollTop()){

        $(window).scrollTop(currentscroll);

        }
    });

1

이거 한번 해봐:

var lastfoucsin;

$('.txtclassname').click(function(e)
{
  lastfoucsin=$(this);

//the virtual keyboard appears automatically

//Do your stuff;

});


//to check ipad virtual keyboard appearance. 
//First check last focus class and close the virtual keyboard.In second click it closes the wrapper & lable

$(".wrapperclass").click(function(e)
{

if(lastfoucsin.hasClass('txtclassname'))
{

lastfoucsin=$(this);//to avoid error

return;

}

//Do your stuff 
$(this).css('display','none');
});`enter code here`

1

이전 답변에서 언급했듯이 키보드가 나타나면 iOS10 에서 window.innerHeight 변수가 올바르게 업데이트되고 이전 버전에 대한 지원이 필요하지 않으므로 다음보다 쉬운 해킹이 발생했습니다. "솔루션".

//keep track of the "expected" height
var windowExpectedSize = window.innerHeight;

//update expected height on orientation change
window.addEventListener('orientationchange', function(){
    //in case the virtual keyboard is open we close it first by removing focus from the input elements to get the proper "expected" size
    if (window.innerHeight != windowExpectedSize){
        $("input").blur();
        $("div[contentEditable]").blur();     //you might need to add more editables here or you can focus something else and blur it to be sure
        setTimeout(function(){
            windowExpectedSize = window.innerHeight;
        },100);
    }else{
        windowExpectedSize = window.innerHeight;
    }
});

//and update the "expected" height on screen resize - funny thing is that this is still not triggered on iOS when the keyboard appears
window.addEventListener('resize', function(){
    $("input").blur();  //as before you can add more blurs here or focus-blur something
    windowExpectedSize = window.innerHeight;
});

다음을 사용할 수 있습니다.

if (window.innerHeight != windowExpectedSize){ ... }

키보드가 보이는지 확인하십시오. 나는 내 웹 응용 프로그램에서 잠시 동안 그것을 사용하고 있지만 잘 작동하지만 (다른 모든 솔루션과 마찬가지로) "예상 된"크기가 올바르게 업데이트되지 않아서 실패하는 상황을 찾을 수 있습니다.


나는 이것이 사실 이었기를 바라고 있었지만, 업데이트되지 않았다.
Sam Saffron

0

검색을했는데 "키보드 표시"또는 "키보드 해제"에 대한 구체적인 내용을 찾을 수 없었습니다. 지원되는 이벤트의 공식 목록을 참조하십시오 . iPad 용 기술 노트 TN2262 도 참조하십시오 . 이미 알고 있듯이 onorientationchange가로 / 세로를 감지하기 위해 연결할 수 있는 신체 이벤트가 있습니다.

마찬가지로, 거친 추측 ... 크기 조정 감지를 시도 했습니까? 뷰포트 변경으로 키보드가 표시 / 숨겨져 서 해당 이벤트가 간접적으로 트리거 될 수 있습니다.

window.addEventListener('resize', function() { alert(window.innerHeight); });

어떤 크기 조정 이벤트에서 새로운 높이를 경고합니다 ....


10
불행히도 내 테스트에서 키보드는 크기 조정 이벤트를 트리거하지 않았습니다.
LKM

0

나는 이것을 직접 시도하지 않았으므로 아이디어는 ...하지만 CSS와 함께 미디어 쿼리를 사용하여 창의 높이가 언제 변경되는지 확인한 다음 디자인을 변경하려고 시도 했습니까? Safari 모바일이 키보드를 창의 일부로 인식하지 않아 희망적으로 작동한다고 생각합니다.

예:

@media all and (height: 200px){
    #content {height: 100px; overflow: hidden;}
}

2
매우 영리한 아이디어. 불행히도 내 테스트에서 키보드를 보여주는 것은 미디어 쿼리를 평가하는 데 사용되는 높이 값에 영향을 미치지 않았습니다.
LKM

나는 확인할 수 있습니다 : height : 250px가 나를 위해 일했습니다 (적어도 안드로이드에서는).
WoodrowShigeru

0

문제는 2014 년에도 소프트 키보드가 열려있는 동안 장치가 화면 크기 조정 이벤트와 스크롤 이벤트를 일관되지 않게 처리한다는 것입니다.

블루투스 키보드를 사용하더라도 iOS는 특히 이상한 레이아웃 버그를 유발한다는 것을 알았습니다. 소프트 키보드를 감지하는 대신 터치 스크린이 매우 좁은 기기를 대상으로해야했습니다.

너비 감지 에는 미디어 쿼리 (또는 window.matchMedia )를 사용하고 터치 이벤트 감지에는 Modernizr 을 사용합니다.


0

아마도 사용자가 '외부 키보드가 연결되어 있습니까?'를 토글 할 수있는 앱 설정에 확인란이 더 쉽습니다.

작은 글씨로, 오늘날의 브라우저에서는 외부 키보드를 감지 할 수 없다고 사용자에게 설명하십시오.


1
이와 같은 토글을 추가하는 것은 앱을 중단시키지 않는 다른 솔루션이 없으면 허용되지 않는 최후의 수단입니다. 이것은 작동하는 앱을 만드는 데 방해가되는 것이 아닙니다.
Adam Leggett

-2

입력 상자에 포커스가있을 때를 감지 할 수 있으며 키보드의 높이를 알 수 있습니다. 화면의 방향을 얻는 데 사용할 수있는 CSS도 있으므로 해킹 할 수 있다고 생각합니다.

그래도 실제 키보드의 경우를 처리하고 싶을 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.