aplikacja internetowa na iPada: wykrywa wirtualną klawiaturę za pomocą JavaScript w Safari?

Piszę aplikację internetową na iPada (nie zwykłą aplikację App Store - jest napisana przy użyciu HTML, CSS i JavaScript). Ponieważ klawiatura wypełnia ogromną część ekranu, sensowne byłoby zmienić układ aplikacji, aby pasował do pozostałej przestrzeni, gdy klawiatura jest wyświetlana. Jednak nie znalazłem sposobu, aby wykryć, kiedy i czy klawiatura jest wyświetlana.

Moim pierwszym pomysłem było założenie, że klawiatura jest widoczna, gdy pole tekstowe ma fokus. Jednak, gdy zewnętrzna klawiatura jest dołączony do ipada, wirtualna klawiatura nie pojawia się, gdy pole tekstowe otrzymuje fokus.

W moich eksperymentach klawiatura również nie wpływała na wysokość ani przewijanie żadnego z elementów DOM, i nie znalazłem żadnych zastrzeżonych zdarzeń lub właściwości, które wskazują, czy klawiatura jest widoczna.

Author: LKM, 2010-04-07

16 answers

Znalazłem rozwiązanie, które działa, chociaż jest trochę brzydkie. Nie sprawdzi się też w każdej sytuacji, ale u mnie działa. Ponieważ dostosowuję rozmiar interfejsu użytkownika do rozmiaru okna iPada, użytkownik zwykle nie może przewijać. Innymi słowy, jeśli ustawię scrollTop okna, pozostanie na 0.

Jeśli z drugiej strony pojawi się klawiatura, przewijanie nagle zadziała. Więc mogę ustawić scrollTop, natychmiast przetestować jego wartość,a następnie zresetować. Oto jak to może wyglądać w kod, używając 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 ');
    });
});

Normalnie oczekiwałbyś, że nie będzie to widoczne dla użytkownika. Niestety, przynajmniej podczas pracy w symulatorze, iPad widocznie (choć szybko) przewija się w górę iw dół. Mimo to działa, przynajmniej w określonych sytuacjach.

Testowałem to na iPadzie i wydaje się, że działa dobrze.
 52
Author: LKM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-21 12:15:45

Możesz użyć zdarzenia focusout do wykrycia zwolnienia klawiatury. To jak smuga, ale bąbelki. Uruchomi się po zamknięciu klawiatury (ale oczywiście również w innych przypadkach). W przeglądarkach Safari i Chrome zdarzenie można zarejestrować tylko za pomocą addEventListener, a nie za pomocą starszych metod. Oto przykład, którego użyłem do przywrócenia aplikacji Phonegap po zwolnieniu klawiatury.

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

Bez tego fragmentu kontener aplikacji pozostawał w pozycji przewijanej w górę do czasu odświeżenia strony.

 27
Author: Per Quested Aronsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-19 08:27:59

Może nieco lepszym rozwiązaniem jest powiązanie (w moim przypadku jQuery) zdarzenia "blur" na różnych polach wejściowych.

To dlatego, że po zniknięciu klawiatury wszystkie pola formularza są zamazane. Więc dla mojej sytuacji ten sniped rozwiązał problem.

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

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

});
Mam nadzieję, że to pomoże. Michele
 15
Author: Michele,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-16 17:38:42

Jeśli istnieje klawiatura ekranowa, skupienie pola tekstowego, które znajduje się w dolnej części okna widoku, spowoduje przewinięcie pola tekstowego w przeglądarce Safari. Może być jakiś sposób na wykorzystanie tego zjawiska w celu wykrycia obecności klawiatury(posiadanie małego pola tekstowego na dole strony, które chwilowo zyskuje ostrość, lub coś w tym stylu).

 14
Author: ianh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-08 09:31:38

Podczas zdarzenia fokus można przewijać wysokość dokumentu i magicznie okno.innerHeight jest zmniejszona o wysokość wirtualnej klawiatury. Zauważ, że rozmiar klawiatury wirtualnej jest inny dla orientacji poziomej i pionowej, więc musisz ją ponownie wykryć, gdy się zmieni. Odradzam zapamiętywanie tych wartości, ponieważ użytkownik może w każdej chwili podłączyć/odłączyć klawiaturę bluetooth.

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;
};

Zauważ, że gdy użytkownik korzysta z klawiatury bluetooth, keyboardHeight to 44, czyli wysokość paska narzędzi [poprzedni] [następny].

Jest trochę migotania, gdy robisz to wykrywanie, ale nie wydaje się możliwe, aby tego uniknąć.

 11
Author: Hafthor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-15 20:03:07

Edit: udokumentowane przez Apple chociaż nie mogłem go uruchomić: WKWebView zachowanie z wyświetlaniem klawiatury: "W iOS 10 obiekty WKWebView pasują do natywnego zachowania Safari, aktualizując swoje okno.właściwość innerHeight, gdy klawiatura jest wyświetlana, i nie wywołaj zdarzeń zmiany rozmiaru" (być może można użyć focus lub focus plus delay, aby wykryć klawiaturę zamiast używać resize).

Edit: kod zakłada klawiaturę ekranową, nie zewnętrzną. Zostawić, bo info może być przydatne do inne, które dbają tylko o klawiatury ekranowe. Use http://jsbin.com/AbimiQup/4 aby wyświetlić strony params.

Testujemy, czy {[1] } jest elementem pokazującym klawiaturę (input type=text, textarea, itd.).

Poniższy kod nadaje rzeczy do naszych celów (choć nie jest ogólnie poprawny).

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');
};

Powyższy kod jest tylko przybliżony: jest niewłaściwy dla Klawiatury dzielonej, niezakręconej, fizycznej. Zgodnie z komentarzem na górze, możesz być w stanie zrobić lepiej zadanie niż podany kod na Safari (od iOS8?) lub WKWebView (od iOS10) przy użyciu właściwości window.innerHeight.

Znalazłem błędy w innych okolicznościach: np. dać focus do wejścia, następnie przejść do ekranu głównego, a następnie wrócić do strony; iPad nie powinien zmniejszyć viewport; stare przeglądarki IE nie będą działać, Opera nie działa, ponieważ Opera utrzymywała focus na elemencie po zamknięciu klawiatury.

Jednak oznaczona odpowiedź (zmiana scrolltop na measure height) ma nieprzyjemne efekty uboczne interfejsu, jeśli viewport zoomable (lub force-zoom włączone w preferencjach). Nie korzystam z innego sugerowanego rozwiązania (zmiana scrolltop), ponieważ na iOS, gdy viewport jest zoomable i przewijanie do focused input, istnieją błędne interakcje między przewijaniem & zoom & focus (które mogą pozostawić tylko focused wejście poza viewport - niewidoczne).

 8
Author: robocat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 04:15:02

Testowane tylko na Androidzie 4.1.1:

Zdarzenie rozmycie nie jest wiarygodnym zdarzeniem do testowania klawiatury w górę iw dół, ponieważ użytkownik jako opcja jawnego ukrycia klawiatury nie wywołuje zdarzenia rozmycia w polu, które spowodowało wyświetlenie klawiatury.

Zdarzenie zmiany rozmiaru działa jak urok, jeśli klawiatura z jakiegokolwiek powodu pojawia się w górę lub w dół.

Kawa:

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

Jest uruchamiany za każdym razem, gdy klawiatura jest pokazana lub Ukryta z jakiegokolwiek powodu.

Uwaga jednak na w przypadku przeglądarki android (zamiast aplikacji) znajduje się wysuwany pasek adresu url, który nie uruchamia zmiany rozmiaru, gdy jest schowany, ale zmienia Dostępny rozmiar okna.

 5
Author: user1650613,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-06 02:08:42

Zamiast wykrywać klawiaturę, spróbuj wykryć rozmiar okna

Jeśli wysokość okna została zmniejszona, a szerokość nadal jest taka sama, oznacza to, że klawiatura jest włączona. Jeśli klawiatura jest wyłączona, możesz również dodać do tego, sprawdzić, czy jakiekolwiek pole wejściowe jest aktywne, czy nie.

Wypróbuj na przykład ten kod.

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()));
    }   
});     
 3
Author: K.A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-10 14:41:29

To rozwiązanie zapamiętuje pozycję przewijania

    var currentscroll = 0;

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

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

        $(window).scrollTop(currentscroll);

        }
    });
 1
Author: WebsterDevelopine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-15 05:07:40

Spróbuj tego:

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
Author: Nalini Amir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-28 09:54:14

Poszperałem trochę i nie mogłem znaleźć nic konkretnego na "na klawiaturze pokazane" lub "na klawiaturze zwolniony". Zobacz oficjalną listę obsługiwanych zdarzeń . Zobacz również Uwaga techniczna TN2262 dla iPada. Jak zapewne już wiesz, istnieje Zdarzenie ciała onorientationchange, które możesz podłączyć do sieci, aby wykryć krajobraz/portret.

Podobnie, ale zgaduję... próbowałeś wykryć zmianę rozmiaru? Zmiany Viewport mogą wywołać to zdarzenie pośrednio z wyświetlonej klawiatury / Ukryty.
window.addEventListener('resize', function() { alert(window.innerHeight); });

Który po prostu ostrzega o nowej wysokości przy każdym zdarzeniu zmiany rozmiaru....

 0
Author: slf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-08 14:24:04

Sam tego nie próbowałem, więc to tylko pomysł... ale czy próbowałeś użyć zapytań o media z CSS, aby zobaczyć, kiedy zmienia się wysokość okna, a następnie zmienić projekt? Wyobrażam sobie, że Safari mobile nie rozpoznaje klawiatury jako części okna, więc miejmy nadzieję, że zadziała.

Przykład:

@media all and (height: 200px){
    #content {height: 100px; overflow: hidden;}
}
 0
Author: Janae,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-05 16:58:45

Problem polega na tym, że nawet w 2014 r. urządzenia obsługują zdarzenia zmiany rozmiaru ekranu, a także zdarzenia przewijania, niekonsekwentnie, gdy miękka klawiatura jest otwarta.

Odkryłem, że nawet jeśli używasz klawiatury bluetooth, iOS w szczególności wyzwala dziwne błędy układu; więc zamiast wykrywać miękką klawiaturę, po prostu musiałem kierować urządzenia, które są bardzo wąskie i mają ekrany dotykowe.

Używam media queries (lub window.matchMedia ) do wykrywania szerokości i Modernizr do wykrywania zdarzeń dotykowych.

 0
Author: pixelbandito,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-07 19:55:53

Jak zaznaczono w poprzednich odpowiedziach gdzieś w oknie .innerheight zmienna jest aktualizowana poprawnie teraz na iOS10 Kiedy pojawia się klawiatura i ponieważ nie potrzebuję wsparcia dla wcześniejszych wersji, wymyśliłem następujący hack, który może być nieco łatwiejsze niż omówione "rozwiązania".

//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;
});

Wtedy możesz użyć:

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

Aby sprawdzić, czy klawiatura jest widoczna. Używam go od jakiegoś czasu w mojej aplikacji internetowej i działa dobrze, ale (jak wszystkie inne rozwiązania) możesz znaleźć sytuację, w której nie powiedzie się, ponieważ "oczekiwany" rozmiar nie jest poprawnie aktualizowany lub coś takiego.

 0
Author: Flow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-24 09:37:08

Być może łatwiej jest mieć pole wyboru w ustawieniach aplikacji, gdzie użytkownik może przełączać ' zewnętrzną klawiaturę dołączoną?'.

Małym drukiem wyjaśnij użytkownikowi, że zewnętrzne klawiatury nie są obecnie wykrywalne w dzisiejszych przeglądarkach.

 0
Author: Ian White,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-13 05:43:38

Cóż, możesz wykryć, kiedy twoje pola wejściowe mają ostrość i znasz wysokość klawiatury. Dostępny jest również CSS, aby uzyskać orientację ekranu, więc myślę, że możesz go zhakować.

Chciałbyś jakoś zająć się sprawą fizycznej klawiatury.

 -1
Author: stuntmouse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-08 11:16:19