application web iPad: détecter le clavier virtuel en utilisant JavaScript dans Safari?

je suis en train d'écrire une application web pour l'iPad ( n'est pas une application régulière de boutique D'applications - il est écrit en utilisant HTML, CSS et JavaScript). Puisque le clavier se remplit d'une grande partie de l'écran, il serait judicieux de modifier l'application de mise en page pour l'adapter à l'espace restant lorsque le clavier est affiché. Cependant, je n'ai trouvé aucun moyen de détecter si le clavier est affiché.

ma première idée était de supposer que le clavier est visible quand un champ de texte a concentrer. Cependant, si un clavier externe est connecté à un iPad, le clavier virtuel ne s'affiche pas lorsqu'un champ de texte reçoit le focus.

au cours de mes expériences, le clavier n'a pas non plus affecté la hauteur ou la hauteur des éléments DOM, et je n'ai trouvé aucun événement ou propriété exclusive qui indique si le clavier est visible.

135
demandé sur LKM 2010-04-07 18:12:24

16 réponses

j'ai trouvé une solution qui fonctionne, bien qu'elle soit un peu laide. Ça ne marchera pas dans toutes les situations, mais ça marche pour moi. Comme j'adapte la taille de l'interface utilisateur à la taille de la fenêtre de l'iPad, l'utilisateur est normalement incapable de faire défiler. En d'autres termes, si je mets le scrollTop de la fenêtre, il restera à 0.

si, par contre, le clavier est affiché, le défilement fonctionne soudainement. Donc je peux régler scrollTop, immédiatement tester sa valeur, puis la Réinitialiser. Voici comment cela pourrait ressembler dans le code, en utilisant 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 ');
    });
});

normalement, vous vous attendez à ce que cela ne soit pas visible à l'utilisateur. Malheureusement, au moins quand il fonctionne dans le simulateur, l'iPad défile visiblement (bien que rapidement) de haut en bas. Encore, il fonctionne, au moins dans certaines situations spécifiques.

j'ai testé ça sur un iPad, et ça semble bien fonctionner.

52
répondu LKM 2010-07-21 12:15:45

vous pouvez utiliser l'événement focus out pour détecter le renvoi du clavier. C'est comme flou, mais des bulles. Il se déclenche lorsque le clavier se ferme (mais aussi dans d'autres cas, bien sûr). Dans Safari et Chrome, l'événement ne peut être enregistré qu'avec addEventListener, pas avec les méthodes traditionnelles. Voici un exemple que j'ai utilisé pour restaurer une application Phonegap après le renvoi du clavier.

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

sans cet extrait, le conteneur app est resté dans le laminé position jusqu'au rafraîchissement de la page.

27
répondu Per Quested Aronsson 2013-10-19 08:27:59

peut-être une solution un peu meilleure est de lier (avec jQuery dans mon cas) l'événement "flou" sur les différents champs d'entrée.

cela parce que lorsque le clavier disparaît tous les champs de formulaire sont flous. Donc, pour ma situation, ceci a résolu le problème.

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

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

});

j'espère que ça aidera. Michele

15
répondu Michele 2010-10-16 17:38:42

S'il y a un clavier à l'écran, la mise au point d'un champ de texte qui est près du bas du viewport obligera Safari à faire défiler le champ de texte dans la vue. Il pourrait y avoir un moyen d'exploiter ce phénomène pour détecter la présence du clavier (ayant un petit champ de texte en bas de la page qui gagne momentanément la mise au point, ou quelque chose comme ça).

14
répondu ianh 2010-04-08 09:31:38

au cours de l'événement focus, vous pouvez faire défiler au-delà de la hauteur du document et magiquement la fenêtre.innerHeight est réduite par la hauteur du clavier virtuel. Notez que la taille du clavier virtuel est différente pour les orientations paysage vs. portrait donc vous aurez besoin de le re-tecter quand il change. Je conseillerais de ne pas se souvenir de ces valeurs car l'utilisateur pourrait se connecter/déconnecter un clavier bluetooth à tout moment.

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

Notez que lorsque l'utilisateur est à l'aide d'un clavier bluetooth, la hauteur du clavier est de 44, ce qui correspond à la hauteur de la barre d'outils [précédente][suivante].

il y a un petit peu de scintillement quand vous faites cette détection, mais il ne semble pas possible de l'éviter.

11
répondu Hafthor 2013-07-15 20:03:07

Edit: Documentées par Apple, bien que je n'ai pas pu le faire fonctionner: WKWebView Comportement avec le Clavier Affiche : "Dans iOS 10, WKWebView objets correspondent Safari natif de comportement par la mise à jour de leur fenêtre.propriété innerHeight lorsque le clavier est affiché, et ne pas appeler redimensionner les événements" (peut-être peut-on utiliser focus ou focus plus delay pour détecter le clavier au lieu d'utiliser redimensionner).

Edit: le code présume le clavier à l'écran, pas le clavier externe. Le laisser parce que l'information peut être utile à d'autres qui se soucient seulement des claviers à l'écran. Use http://jsbin.com/AbimiQup/4 pour voir la page params.

nous testons pour voir si le document.activeElement est un élément qui montre le clavier (Type d'entrée=texte, textarea, etc).

le code suivant esquive des choses à nos fins (bien qu'il ne soit pas généralement correct).

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

le code ci-dessus n'est qu'approximatif: il est mauvais pour les claviers fractionnés, les claviers dévoqués, les claviers physiques. Selon le commentaire de top, vous pourriez être en mesure de faire un meilleur travail que le code donné sur Safari (depuis iOS8?) ou WKWebView (depuis iOS10) en utilisant la propriété window.innerHeight .

j'ai trouvé des échecs dans d'autres circonstances: par exemple, donner la priorité à l'entrée puis aller à l'écran d'accueil puis revenir à la page; iPad ne devrait pas rendre le viewport plus petit; anciens navigateurs IE ne fonctionnera pas, Opera ne fonctionne pas parce que Opera gardé la priorité sur l'élément après clavier fermé.

cependant la réponse étiquetée (changer le scrolltop pour mesurer la hauteur) a des effets secondaires désagréables si le zoomable de viewport (ou Force-zoom activé dans les préférences). Je n'utilise pas l'autre solution suggérée (changer de scrolltop) parce que sur iOS, quand viewport est zoomable et défile vers une entrée focalisée, il y a des interactions buggées entre défilement et zoom & focus (qui peuvent laisser une entrée juste focalisée en dehors de viewport - pas visible).

8
répondu robocat 2018-03-26 04:15:02

testé uniquement sur Android 4.1.1:

événement flou n'est pas un événement fiable pour tester clavier haut et bas parce que l'utilisateur comme l'option de cacher explicitement le clavier qui ne déclenche pas un événement flou sur le champ qui a causé le clavier à montrer.

redimensionne l'événement cependant fonctionne comme un charme si le clavier monte ou descend pour une raison quelconque.

café:

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

allume à tout moment le clavier est affiché ou masqué pour une raison quelconque.

notez cependant sur dans le cas d'un navigateur android (plutôt qu'une application) il y a une barre d'url rétractable qui ne démarre pas redimensionner quand il est rétracté tout en changeant la taille de fenêtre disponible.

5
répondu user1650613 2012-09-06 02:08:42

au Lieu de détecter le clavier, essayez de détecter la taille de la fenêtre

Si la hauteur de la fenêtre a été réduite, et la largeur est toujours le même, cela signifie que le clavier est sur. Sinon le clavier est désactivé, vous pouvez également ajouter à la, tester si un champ de saisie est activée ou pas.

essayez ce code par exemple.

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
répondu K.A 2014-09-10 14:41:29

Cette solution se souvient de la position de défilement

    var currentscroll = 0;

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

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

        $(window).scrollTop(currentscroll);

        }
    });
1
répondu WebsterDevelopine 2013-05-15 05:07:40

essayez celui-ci:

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
répondu Nalini Amir 2014-08-28 09:54:14

j'ai fait quelques recherches, et je n'ai rien trouvé de concret pour un" sur le clavier montré "ou"sur le clavier rejeté". Voir la liste officielle des événements soutenus . Voir aussi Note technique TN2262 pour iPad. Comme vous le savez probablement déjà, il y a un événement corporel onorientationchange que vous pouvez brancher pour détecter paysage/portrait.

de même, mais une supposition sauvage... avez-vous essayé de détecter redimensionner? Les changements de Viewport peuvent déclencher cet événement indirectement à partir du clavier étant affiché / caché.

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

qui avertirait simplement la nouvelle hauteur sur n'importe quel événement de redimensionnement....

0
répondu slf 2010-04-08 14:24:04

je n'ai pas essayé moi-même, alors c'est juste une idée... mais avez-vous essayé d'utiliser media queries avec CSS pour voir quand la hauteur de la fenêtre change et puis changer la conception pour cela? J'imagine que Safari mobile ne reconnaît pas le clavier comme faisant partie de la fenêtre, donc j'espère que ça marchera.

exemple:

@media all and (height: 200px){
    #content {height: 100px; overflow: hidden;}
}
0
répondu Janae 2014-08-05 16:58:45

le problème est que, même en 2014, les appareils gèrent les événements de redimensionnement d'écran, ainsi que les événements de défilement, de manière incohérente pendant que le clavier souple est ouvert.

j'ai trouvé que, même si vous utilisez un clavier bluetooth, iOS en particulier déclenche quelques bugs de mise en page étranges; donc au lieu de détecter un clavier doux, j'ai juste eu à cibler des appareils qui sont très étroits et ont des écrans tactiles.

j'utilise les requêtes des médias (ou la fenêtre .matchMedia ) pour la détection de largeur et Modernizr pour la détection d'événements tactiles.

0
répondu pixelbandito 2015-07-07 19:55:53

comme indiqué dans les réponses précédentes quelque part dans la fenêtre .la variable innerHeight est mise à jour correctement maintenant sur iOS10 lorsque le clavier apparaît et puisque je n'ai pas besoin du support pour les versions précédentes, j'ai trouvé le hack suivant qui pourrait être un peu plus facile que les "solutions"discutées.

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

alors vous pouvez utiliser:

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

pour vérifier si le clavier est visible. Je l'ai utilisé pendant un certain temps maintenant dans mon application web et il fonctionne bien, mais (comme toutes les autres solutions) vous pourriez trouver une situation où il échoue parce que la taille "attendue" n'est pas mis à jour correctement ou quelque chose.

0
répondu Flow 2017-04-24 09:37:08

peut-être est-il plus facile d'avoir une case à cocher dans les paramètres de votre application où l'utilisateur peut basculer 'clavier externe attaché?'.

En petits caractères, expliquer à l'utilisateur que les claviers externes sont actuellement pas détectable dans les navigateurs d'aujourd'hui.

0
répondu Ian White 2017-12-13 05:43:38

Eh bien, vous pouvez détecter quand vos boîtes d'entrée ont la mise au point, et vous savez la hauteur du clavier. Il est également CSS disponibles pour obtenir l'orientation de l'écran, donc je pense que vous pouvez pirater.

vous voudriez gérer le cas d'un clavier physique en quelque sorte, cependant.

-1
répondu stuntmouse 2010-04-08 11:16:19