iOS 5 фиксированное позиционирование и виртуальная клавиатура - PullRequest
135 голосов
/ 01 ноября 2011

У меня есть мобильный веб-сайт, у которого div прикреплен к нижней части экрана с помощью позиции: исправлено.Все отлично работает в iOS 5 (я тестирую на iPod Touch), пока не окажусь на странице с формой.Когда я нажимаю на поле ввода и появляется виртуальная клавиатура, внезапно фиксированная позиция моего div теряется.Теперь div прокручивает страницу до тех пор, пока клавиатура видна.Как только я нажимаю «Готово», чтобы закрыть клавиатуру, div возвращается в свое положение в нижней части экрана и подчиняется правилу position: fixed.

Кто-нибудь еще сталкивался с подобным поведением?Это ожидается?Спасибо.

Ответы [ 25 ]

48 голосов
/ 21 марта 2013

У меня была эта проблема в моем приложении. Вот как я работаю над этим:

input.on('focus', function(){
    header.css({position:'absolute'});
});
input.on('blur', function(){
    header.css({position:'fixed'});
});

Я просто прокручиваю вверх и размещаю его там, чтобы пользователь iOS не заметил ничего странного. Оберните это при обнаружении некоторых пользовательских агентов, чтобы другие пользователи не получали такое поведение.

15 голосов
/ 28 сентября 2012

У меня была немного другая проблема с ipad, когда виртуальная клавиатура выводила мой экран за пределы экрана.Затем, после того, как пользователь закрыл виртуальную клавиатуру, мой видовой экран все еще оставался за кадром.В моем случае я сделал что-то вроде следующего:

var el = document.getElementById('someInputElement');
function blurInput() {
    window.scrollTo(0, 0);
}
el.addEventListener('blur', blurInput, false);
14 голосов
/ 05 февраля 2013

Это код, который мы используем для решения проблемы с ipad. Он в основном обнаруживает расхождения между смещением и положением прокрутки - это означает, что «исправлено» не работает правильно.

$(window).bind('scroll', function () {
    var $nav = $(".navbar")
    var scrollTop = $(window).scrollTop();
    var offsetTop = $nav.offset().top;

    if (Math.abs(scrollTop - offsetTop) > 1) {
        $nav.css('position', 'absolute');
        setTimeout(function(){
            $nav.css('position', 'fixed');
        }, 1);
    }
});
12 голосов
/ 06 февраля 2012

Элементы с фиксированным положением просто не обновляют свое положение, когда клавиатура поднята.Я обнаружил, что, обманув Safari, решил, что размер страницы изменился, однако элементы будут перемещаться самостоятельно.Это не идеально, но, по крайней мере, вам не нужно беспокоиться о переключении на «position: absolute» и отслеживании изменений самостоятельно.

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

    var needsScrollUpdate = false;
    $(document).scroll(function(){
        if(needsScrollUpdate) {
            setTimeout(function() {
                $("body").css("height", "+=1").css("height", "-=1");
            }, 0);
        }
    });
    $("input, textarea").live("focus", function(e) {
        needsScrollUpdate = true;
    });

    $("input, textarea").live("blur", function(e) {
        needsScrollUpdate = false;
    });
6 голосов
/ 28 февраля 2013

На всякий случай, если кто-нибудь натолкнется на эту тему, как я делал, исследуя эту проблему.Я нашел эту ветку полезной для стимулирования моего мышления по этому вопросу.

Это было мое решение для этого в недавнем проекте.Вам просто нужно изменить значение «targetElem» на селектор jQuery, который представляет ваш заголовок.

if(navigator.userAgent.match(/iPad/i) != null){

var iOSKeyboardFix = {
      targetElem: $('#fooSelector'),
      init: (function(){
        $("input, textarea").on("focus", function() {
          iOSKeyboardFix.bind();
        });
      })(),

      bind: function(){
            $(document).on('scroll', iOSKeyboardFix.react);  
                 iOSKeyboardFix.react();      
      },

      react: function(){

              var offsetX  = iOSKeyboardFix.targetElem.offset().top;
              var scrollX = $(window).scrollTop();
              var changeX = offsetX - scrollX; 

              iOSKeyboardFix.targetElem.css({'position': 'fixed', 'top' : '-'+changeX+'px'});

              $('input, textarea').on('blur', iOSKeyboardFix.undo);

              $(document).on('touchstart', iOSKeyboardFix.undo);
      },

      undo: function(){

          iOSKeyboardFix.targetElem.removeAttr('style');
          document.activeElement.blur();
          $(document).off('scroll',iOSKeyboardFix.react);
          $(document).off('touchstart', iOSKeyboardFix.undo);
          $('input, textarea').off('blur', iOSKeyboardFix.undo);
      }
};

};

Существует небольшая задержка в принятии исправления, потому что iOS останавливает манипулирование DOM, пока онопрокрутка, но это делает трюк ...

4 голосов
/ 03 июля 2013

Эта проблема действительно раздражает.

Я объединил некоторые из вышеупомянутых методов и придумал следующее:

$(document).on('focus', 'input, textarea', function() {
    $('.YOUR-FIXED-DIV').css('position', 'static');
});

$(document).on('blur', 'input, textarea', function() {
    setTimeout(function() {
        $('.YOUR-FIXED-DIV').css('position', 'fixed');
        $('body').css('height', '+=1').css('height', '-=1');
    }, 100);
});

У меня есть две фиксированные навигационные панели (верхний и нижний колонтитулы, используя Twitter начальной загрузки). Оба действовали странно, когда клавиатура поднята, и снова странно, когда клавиатура нажата.

С этим временным / отложенным исправлением все работает. Время от времени я все еще нахожу сбой, но, кажется, этого достаточно, чтобы показать его клиенту.

Дайте мне знать, если это работает для вас. Если нет, мы можем найти что-то еще. Благодаря.

4 голосов
/ 30 августа 2012

Ни один из других ответов, которые я нашел для этой ошибки, не работал для меня. Я смог это исправить, просто прокрутив страницу вверх на 34 пикселя, то есть на уровне мобильного сафари. с JQuery:

$('.search-form').on('focusin', function(){
    $(window).scrollTop($(window).scrollTop() + 34);
});

Это очевидно вступит в силу во всех браузерах, но предотвращает его взлом в iOS.

3 голосов
/ 08 июня 2014

Я взял Jory Cunningham ответа и улучшил его:

Во многих случаях сходит с ума не один элемент, а несколько элементов с фиксированным позиционированием, поэтому в этом случае targetElem должен быть объектом jQuery, в котором есть все фиксированные элементы, которые вы хотите «исправить». Хо, похоже, клавиатура iOS исчезнет, ​​если вы прокрутите ...

Нет необходимости упоминать, что вы должны использовать это ПОСЛЕ документ DOM ready событие или непосредственно перед закрывающим тегом </body>.

(function(){
    var targetElem = $('.fixedElement'), // or more than one
        $doc       = $(document),
        offsetY, scrollY, changeY;

    if( !targetElem.length || !navigator.userAgent.match(/iPhone|iPad|iPod/i) )
        return;

    $doc.on('focus.iOSKeyboardFix', 'input, textarea, [contenteditable]', bind);

    function bind(){
        $(window).on('scroll.iOSKeyboardFix', react);
        react();
    }

    function react(){
        offsetY = targetElem.offset().top;
        scrollY = $(window).scrollTop();
        changeY = offsetY - scrollY;

        targetElem.css({'top':'-'+ changeY +'px'});

        // Instead of the above, I personally just do:
        // targetElem.css('opacity', 0);

        $doc.on('blur.iOSKeyboardFix', 'input, textarea, [contenteditable]', unbind)
            .on('touchend.iOSKeyboardFix', unbind);
    }

    function unbind(){
        targetElem.removeAttr('style');
        document.activeElement.blur();

        $(window).off('scroll.iOSKeyboardFix');
        $doc.off('touchend.iOSKeyboardFix blur.iOSKeyboardFix');
    }
})();
3 голосов
/ 17 августа 2014

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

Все начало работать, когда я добавил этот метатег в html.

<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,height=device-height" >

Часть, которая имела значение:

height=device-height

Надеюсь, это кому-нибудь поможет.

2 голосов
/ 12 ноября 2013

У меня есть решение, похожее на @NealJMD, за исключением того, что мое выполняется только для iOS и правильно определяет смещение прокрутки, измеряя scollTop до и после прокрутки встроенной клавиатуры, а также используя setTimeout, чтобы разрешить происходящую прокрутку:

var $window = $(window);
var initialScroll = $window.scrollTop();
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
  setTimeout(function () {
    $window.scrollTop($window.scrollTop() + (initialScroll - $window.scrollTop()));
  }, 0);
}
...