iPad Web App: обнаружение виртуальной клавиатуры с помощью JavaScript в Safari?

Я пишу веб-приложение для iPad (не обычное приложение App Store - Он написан с использованием HTML, CSS и JavaScript). Поскольку клавиатура заполняет огромную часть экрана, имеет смысл изменить макет приложения, чтобы соответствовать оставшемуся пространству при отображении клавиатуры. Однако я не нашел способа определить, когда и отображается ли клавиатура.

первой мыслью было предположить, что клавиатура видна, когда текстовое поле имеет фокус. Однако, когда внешняя клавиатура подключена к iPad, виртуальная клавиатура не отображается, когда текстовое поле получает фокус.

в моих экспериментах клавиатура также не влияла на высоту или высоту прокрутки любого из элементов DOM, и я не нашел проприетарных событий или свойств, которые указывают, видна ли клавиатура.

16 ответов


Я нашел решение, которое работает, хотя это немного некрасиво. Это также не будет работать в каждой ситуации, но это работает для меня. Поскольку я адаптирую размер пользовательского интерфейса к размеру окна iPad, пользователь обычно не может прокручивать. Другими словами, если я установлю крышку прокрутки окна, она останется на 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, и, похоже, он работает нормально.


можно использовать focusout событие для обнаружения увольнения клавиатуры. Это как пятно, но пузырьки. Он будет срабатывать, когда клавиатура закрывается (но и в других случаях, конечно). В Safari и Chrome событие может быть зарегистрировано только с помощью addEventListener, а не с помощью устаревших методов. Вот пример, который я использовал для восстановления приложения Phonegap после увольнения клавиатуры.

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

без этого фрагмента контейнер приложения оставался в положении прокрутки вверх до страницы обновить.


возможно, немного лучшее решение-связать (с jQuery в моем случае) событие "размытие" на различных полях ввода.

это потому, что когда клавиатура исчезает, все поля формы размыты. Так что для моей ситуации это snipped решило проблему.

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

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

});

надеюсь, что это помогает. Микеле


Если есть экранная клавиатура, фокусировка текстового поля, которое находится в нижней части окна просмотра, заставит Safari прокрутить текстовое поле в поле зрения. Возможно, есть способ использовать это явление для обнаружения присутствия клавиатуры (с крошечным текстовым полем внизу страницы, которое мгновенно фокусируется или что-то в этом роде).


во время события фокуса вы можете прокручивать высоту документа и волшебным образом окно.innerHeight уменьшается на высоту виртуальной клавиатуры. Обратите внимание, что размер виртуальной клавиатуры отличается для альбомной и портретной ориентации, поэтому вам нужно будет переопределить ее при изменении. Я бы не советовал запоминать эти значения, поскольку пользователь может подключить/отключить клавиатуру 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;
};

обратите внимание, что когда пользователь использует bluetooth клавиатура, keyboardHeight-44, который является высотой панели инструментов [предыдущий][следующий].

когда вы делаете это обнаружение, есть крошечный мерцание, но, похоже, его невозможно избежать.


Edit: документировано Apple, хотя я не мог заставить его работать: WKWebView поведение с дисплеями клавиатуры: "в iOS 10 объекты WKWebView соответствуют собственному поведению Safari, обновляя свое окно.свойство innerHeight при отображении клавиатуры и не вызывайте события изменения размера" (возможно, можно использовать фокус или фокус плюс задержка для обнаружения клавиатуры вместо изменения размера).

Edit: код предполагает экранную клавиатуру, а не внешнюю клавиатуру. Оставляя его, потому что информация может быть полезно для других, которые заботятся только о экранных клавиатурах. Используйте http://jsbin.com/AbimiQup/4 просмотреть параметры страницы.

мы проверяем, чтобы увидеть, если document.activeElement - элемент, который показывает клавиатуру (тип ввода=текст, textarea и т. д.).

следующий код подделывает вещи для наших целей (хотя и не совсем корректно).

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

приведенный выше код является только приблизительным: это неправильно для split keyboard, undocked keyboard, physical keyboard. Согласно комментарий вверху, вы можете сделать лучшую работу, чем данный код на Safari (начиная с iOS8?) или WKWebView (начиная с iOS10) с помощью window.innerHeight собственность.

я обнаружил сбои при других обстоятельствах: например, дайте фокус на ввод, затем перейдите на главный экран, затем вернитесь на страницу; iPad не должен уменьшать видовой экран; старые браузеры IE не будут работать, Opera не работала, потому что Opera держала фокус на элементе после закрытия клавиатуры.

однако помеченный ответ (изменение scrolltop на измерение высоты) имеет неприятные побочные эффекты пользовательского интерфейса, если масштабирование видового экрана (или принудительное масштабирование включено в настройках). Я не использую другое предлагаемое решение (изменение scrolltop), потому что в iOS, когда viewport масштабируется и прокручивается до сфокусированного ввода, есть багги - взаимодействия между прокруткой и масштабированием и фокусом (которые могут оставить только сфокусированный вход за пределами viewport-не виден).


протестировано только на Android 4.1.1:

событие размытия не является надежным событием для проверки клавиатуры вверх и вниз, потому что пользователь в качестве опции явно скрыть клавиатуру, которая не вызывает событие размытия на поле, которое вызвало клавиатуру, чтобы показать.

событие resize работает как шарм, если клавиатура идет вверх или вниз по какой-либо причине.

кофе:

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

срабатывает в любое время, когда клавиатура отображается или скрыта для любого причина.

Примечание однако в случае браузера android (а не приложения) есть выдвижной url-бар, который не срабатывает изменить размер, когда он убирается еще изменить доступный размер окна.


вместо обнаружения клавиатуры, попробуйте определить размер окна

Если высота окна уменьшается, а ширина все та же, это означает, что клавиатура на. В противном случае клавиатура выключена, вы также можете добавить к этому, проверить, находится ли какое-либо поле ввода в фокусе или нет.

попробуйте этот код для примера.

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

Это решение, запоминает позицию прокрутки

    var currentscroll = 0;

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

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

        $(window).scrollTop(currentscroll);

        }
    });

попробуй это:

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`

Я сделал некоторые поиски, и я не мог найти ничего конкретного для "на клавиатуре показано" или "на клавиатуре уволен". См.официальный список поддерживаемых событий. Также смотрите техническое Примечание TN2262 для iPad. Как вы, вероятно, уже знаете, есть событие тела onorientationchange вы можете подключить, чтобы обнаружить пейзаж/портрет.

аналогично, но дикая догадка... вы пытались обнаружить изменение размера? Изменения Viewport могут вызвать это событие косвенно из клавиатура отображается / скрыта.

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

который просто предупредит новую высоту о любом событии изменения размера....


Я не пробовал это сам, так что это просто идея... но вы пробовали использовать медиа-запросы с CSS, чтобы увидеть, когда высота окна изменяется, а затем изменить дизайн для этого? Я бы предположил, что Safari mobile не распознает клавиатуру как часть окна, так что, надеюсь, это сработает.

пример:

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

проблема в том, что даже в 2014 году устройства обрабатывают события изменения размера экрана, а также события прокрутки, непоследовательно, пока открыта мягкая клавиатура.

Я обнаружил, что, даже если вы используете клавиатуру bluetooth, iOS, в частности, вызывает некоторые странные ошибки макета; поэтому вместо обнаружения мягкой клавиатуры мне просто пришлось нацелиться на устройства, которые очень узкие и имеют сенсорные экраны.

Я использую медиа-запросы (или


Как отмечалось в предыдущих ответах где-то окно.innerheight переменная обновляется правильно теперь на iOS10 когда появляется клавиатура, и поскольку мне не нужна поддержка более ранних версий, я придумал следующий хак, который может быть немного проще, чем обсуждаемые "решения".

//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){ ... }

чтобы проверить, видна ли клавиатура. Я использую его некоторое время в своем веб-приложении, и он работает хорошо, но (как все другие решения) вы можете найти ситуацию, когда она терпит неудачу, потому что" ожидаемый " размер не обновляется должным образом или что-то еще.


возможно, проще установить флажок в настройках Вашего приложения, где пользователь может переключать "внешнюю клавиатуру"?'.

мелким шрифтом объясните пользователю, что внешние клавиатуры в настоящее время не обнаруживаются в современных браузерах.


Ну, вы можете обнаружить, когда ваши поля ввода имеют фокус, и вы знаете высоту клавиатуры. Существует также CSS, доступный для получения ориентации экрана, поэтому я думаю, что вы можете взломать его.

вы хотели бы как-то справиться с корпусом физической клавиатуры.