App Web per iPad: rileva la tastiera virtuale utilizzando JavaScript in Safari?

Sto scrivendo un’app Web per iPad ( non una normale app App – è scritta usando HTML, CSS e JavaScript). Poiché la tastiera occupa una parte enorme dello schermo, sarebbe opportuno cambiare il layout dell’app per adattarlo allo spazio rimanente quando viene visualizzata la tastiera. Tuttavia, non ho trovato alcun modo per rilevare quando o se viene mostrata la tastiera.

La mia prima idea era di presumere che la tastiera sia visibile quando un campo di testo è attivo. Tuttavia, quando una tastiera esterna è collegata a un iPad, la tastiera virtuale non viene visualizzata quando un campo di testo riceve lo stato attivo.

Nei miei esperimenti, anche la tastiera non ha influenzato l’altezza o la altezza di scorrimento di nessuno degli elementi DOM, e non ho trovato eventi proprietari o proprietà che indicano se la tastiera è visibile.

Ho trovato una soluzione che funziona, anche se è un po ‘brutta. Inoltre non funzionerà in ogni situazione, ma funziona per me. Poiché sto adattando la dimensione dell’interfaccia utente alle dimensioni della finestra dell’iPad, l’utente non è in genere in grado di scorrere. In altre parole, se imposto lo scrollTop della finestra, rimarrà a 0.

Se, d’altra parte, viene mostrata la tastiera, lo scorrimento funziona improvvisamente. Quindi posso impostare scrollTop, testarne immediatamente il valore e quindi resettarlo. Ecco come potrebbe apparire nel codice, usando 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 '); }); }); 

Normalmente, ti aspetteresti che questo non sia visibile all’utente. Sfortunatamente, almeno durante l’esecuzione nel simulatore, l’iPad visibilmente (anche se rapidamente) scorre su e giù di nuovo. Tuttavia, funziona, almeno in alcune situazioni specifiche.

L’ho provato su un iPad e sembra funzionare bene.

È ansible utilizzare l’evento di messa a fuoco per rilevare il licenziamento della tastiera. È come la sfocatura, ma bolle. Si spara quando la tastiera si chiude (ma anche in altri casi, ovviamente). In Safari e Chrome l’evento può essere registrato solo con addEventListener, non con metodi legacy. Ecco un esempio che ho usato per ripristinare un’app PhoneGap dopo il congedo della tastiera.

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

Senza questo snippet, il contenitore dell’app restava nella posizione di scorrimento verso l’alto fino all’aggiornamento della pagina.

forse una soluzione leggermente migliore è quella di associare (con jQuery nel mio caso) l’evento “blur” sui vari campi di input.

Questo perché quando la tastiera scompare tutti i campi del modulo sono sfocati. Quindi per la mia situazione questo problema ha risolto il problema.

 $('input, textarea').bind('blur', function(e) { // Keyboard disappeared window.scrollTo(0, 1); }); 

spero che sia d’aiuto. Michele

Se è presente una tastiera su schermo, la messa a fuoco di un campo di testo vicino alla parte inferiore della finestra fa sì che Safari scorra il campo di testo in visualizzazione. Potrebbe esserci un modo per sfruttare questo fenomeno per rilevare la presenza della tastiera (con un campo di testo minuscolo nella parte inferiore della pagina che acquisisce momentaneamente la messa a fuoco o qualcosa del genere).

Durante l’evento di messa a fuoco è ansible scorrere oltre l’altezza del documento e magicamente la finestra. L’altezza dell’altezza viene ridotta dall’altezza della tastiera virtuale. Tieni presente che la dimensione della tastiera virtuale è diversa per gli orientamenti orizzontale / verticale, quindi dovrai reimpostare l’immagine quando cambia. Vorrei sconsigliare di ricordare questi valori in quanto l’utente può connettersi / disconnettere una tastiera bluetooth in qualsiasi momento.

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

Si noti che quando l’utente utilizza una tastiera Bluetooth, il valore KeyboardHeight è 44, che corrisponde all’altezza della barra [precedente] [successiva].

C’è un po ‘di sfarfallio quando fai questo rilevamento, ma non sembra ansible evitarlo.

Modifica: Documentato da Apple anche se non riuscivo a farlo funzionare: WKWebView Behavior with Keyboard Displays : “In iOS 10, gli oggetti WKWebView corrispondono al comportamento nativo di Safari aggiornando la proprietà window.innerHeight quando viene visualizzata la tastiera e non chiamano ridimensiona gli eventi “(forse è ansible utilizzare la messa a fuoco o la messa a fuoco più il ritardo per rilevare la tastiera anziché utilizzare il ridimensionamento).

Modifica: il codice presume la tastiera su schermo, non la tastiera esterna. Lasciandolo perché le informazioni potrebbero essere utili agli altri che si interessano solo delle tastiere su schermo. Utilizzare http://jsbin.com/AbimiQup/4 per visualizzare i parametri della pagina.

Testiamo per vedere se document.activeElement è un elemento che mostra la tastiera (tipo di input = testo, area di testo, ecc.).

Il seguente codice fonde le cose per i nostri scopi (sebbene non siano generalmente corretti).

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

Il codice sopra riportato è solo approssimativo: è sbagliato per tastiera divisa, tastiera sganciata, tastiera fisica. Come da commento in alto, potresti essere in grado di fare un lavoro migliore del codice dato su Safari (da iOS8?) O WKWebView (da iOS10) usando la proprietà window.innerHeight .

Ho riscontrato errori in altre circostanze: ad esempio, concentra l’attenzione sull’ingresso, quindi vai alla schermata principale e poi torna alla pagina; iPad non dovrebbe rendere più piccola la vista; i vecchi browser IE non funzionano, Opera non ha funzionato perché Opera ha mantenuto l’attenzione sull’elemento dopo la chiusura della tastiera.

Tuttavia la risposta taggata (cambiando lo scrolltop per misurare l’altezza) ha effetti secondari UI sgradevoli se viewport zoomable (o force-zoom abilitato nelle preferenze). Non utilizzo l’altra soluzione suggerita (cambiando lo scrolltop) perché su iOS, quando viewport è zoomabile e scorre verso input focalizzati, ci sono interazioni buggy tra scrolling e zoom e focus (che può lasciare un input appena focalizzato al di fuori di viewport – non visibile).

Testato solo su Android 4.1.1:

l’evento sfocatura non è un evento affidabile per testare la tastiera su e giù perché l’utente come opzione per hide esplicitamente la tastiera che non triggers un evento di sfocatura sul campo che ha causato la visualizzazione della tastiera.

l’evento di ridimensionamento funziona comunque come un incantesimo se la tastiera viene sollevata o abbassata per qualsiasi motivo.

caffè:

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

viene triggersto ogni volta che la tastiera viene visualizzata o nascosta per qualsiasi motivo.

Nota comunque nel caso di un browser Android (piuttosto che app) c’è una barra di url retrattile che non si triggers ridimensiona quando viene ritirata, ma cambia la dimensione della finestra disponibile.

Invece di rilevare la tastiera, prova a rilevare la dimensione della finestra

Se l’altezza della finestra è stata ridotta e la larghezza è sempre la stessa, significa che la tastiera è accesa. Altrimenti la tastiera è spenta, puoi anche aggiungerla, testare se qualche campo di input è a fuoco o meno.

Prova questo codice per esempio.

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

Questa soluzione ricorda la posizione di scorrimento

  var currentscroll = 0; $('input').bind('focus',function() { currentscroll = $(window).scrollTop(); }); $('input').bind('blur',function() { if(currentscroll != $(window).scrollTop()){ $(window).scrollTop(currentscroll); } }); 

Prova questo:

 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` 

Ho fatto qualche ricerca, e non ho trovato nulla di concreto per un “sulla tastiera mostrata” o “sulla tastiera ignorata”. Consulta l’elenco ufficiale degli eventi supportati . Vedi anche la nota tecnica TN2262 per iPad. Come probabilmente già saprai, c’è un evento body onorientationchange che puoi cablare per rilevare landscape / portrait.

Allo stesso modo, ma un’ipotesi selvaggia … hai provato a rilevare il ridimensionamento? Le modifiche alla vista possono far scattare quell’evento indirettamente dalla tastiera che viene mostrata / nascosta.

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

Il che allerterebbe semplicemente la nuova altezza su qualsiasi evento di ridimensionamento ….

Non l’ho mai provato, quindi è solo un’idea … ma hai provato a usare le media query con i CSS per vedere quando l’altezza della finestra cambia e poi cambiare il disegno per quello? Immagino che Safari mobile non riconosca la tastiera come parte della finestra, quindi spero che funzionerà.

Esempio:

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

Il problema è che, anche nel 2014, i dispositivi gestiscono gli eventi di ridimensionamento schermo, nonché gli eventi di scorrimento, in modo incoerente mentre la tastiera virtuale è aperta.

Ho scoperto che, anche se stai usando una tastiera bluetooth, iOS in particolare triggers alcuni strani bug di layout; quindi, invece di rilevare una tastiera virtuale, ho dovuto semplicemente indirizzare dispositivi molto stretti e dotati di touchscreen.

Uso le media query (o window.matchMedia ) per il rilevamento della larghezza e Modernizr per il rilevamento degli eventi di touch.

Come indicato nelle precedenti risposte, da qualche parte la variabile window.innerHeight viene aggiornata correttamente ora su iOS10 quando appare la tastiera e poiché non ho bisogno del supporto per le versioni precedenti, ho trovato il seguente trucco che potrebbe essere un po ‘più semplice di quello discusso “soluzioni”.

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

allora puoi usare:

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

per verificare se la tastiera è visibile. L’ho usato per un po ‘ora nella mia app Web e funziona bene, ma (come tutte le altre soluzioni) si potrebbe trovare una situazione in cui non riesce perché la dimensione “prevista” non viene aggiornata correttamente o qualcosa del genere.

Forse è più semplice avere una casella di controllo nelle impostazioni della tua app in cui l’utente può triggersre la ‘tastiera esterna collegata?’.

In caratteri piccoli, spiega all’utente che attualmente le tastiere esterne non sono rilevabili nei browser attuali.

Bene, è ansible rilevare quando le windows di input hanno il focus e si conosce l’altezza della tastiera. Sono disponibili anche i CSS per ottenere l’orientamento dello schermo, quindi penso che tu possa modificarlo.

In ogni caso, vorresti gestire il caso di una tastiera fisica.