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

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

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

Ответы [ 25 ]

1 голос
/ 02 июля 2013

Я исправил фиксированное положение содержимого основного макета Ipad следующим образом:

var mainHeight;
var main = $('.main');

// hack to detects the virtual keyboard close action and fix the layout bug of fixed elements not being re-flowed
function mainHeightChanged() {
    $('body').scrollTop(0);
}

window.setInterval(function () {
    if (mainHeight !== main.height())mainHeightChanged();
    mainHeight = main.height();
}, 100);
1 голос
/ 09 февраля 2017

Мой ответ таков: это невозможно.

Я вижу 25 ответов, но ни один из них не работает в моем случае.Вот почему Yahoo и другие страницы скрывают фиксированный заголовок, когда клавиатура включена.И Bing превращает всю страницу в не прокручиваемую (overflow-y: скрытый).

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

1 голос
/ 13 марта 2014

у меня работает

if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
    $(document).on('focus', 'input, textarea', function() {
        $('header').css({'position':'static'});
    });
    $(document).on('blur', 'input, textarea', function() {
        $('header').css({'position':'fixed'});
    });
}
1 голос
/ 31 августа 2013

У меня была похожая проблема с @ ds111 s.Мой сайт был перемещен клавиатурой вверх, но не закрывался при закрытии клавиатуры.

Сначала я попробовал решение @ ds111, но у меня было два поля input.Конечно, сначала клавиатура исчезает, затем происходит размытие (или что-то в этом роде).Таким образом, второй input находился под клавиатурой, когда фокус переключался непосредственно с одного входа на другой.

Кроме того, «подпрыгивание» было недостаточно для меня, поскольку вся страница имеет толькоразмер ipad.Поэтому я сделал прокрутку плавной.

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

Все вместе я могуобъясните следующий фрагмент javascript следующим образом: Присоедините следующий слушатель событий размытия к текущему и всем будущим input и textarea (= live): дождитесь льготного периода (= window.setTimeout(..., 10)) и плавно прокрутите вверх (=animate({scrollTop: 0}, ...)), но только если «не показана клавиатура» (= if($('input:focus, textarea:focus').length == 0)).

$('input, textarea').live('blur', function(event) {
    window.setTimeout(function() {
        if($('input:focus, textarea:focus').length == 0) {
            $("html, body").animate({ scrollTop: 0 }, 400);
        }
    }, 10)
})

Имейте в виду, что льготный период (= 10) может быть слишком коротким или клавиатура можетвсе еще будет отображаться, хотя input или textarea не будут сфокусированы.Конечно, если вы хотите прокрутить быстрее или медленнее, вы можете настроить продолжительность (= 400)

1 голос
/ 10 июля 2014

В нашем случае это исправится, как только пользователь выполнит прокрутку. Так что это исправление, которое мы использовали для имитации прокрутки на blur на любом input или textarea:

$(document).on('blur', 'input, textarea', function () {
    setTimeout(function () {
        window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
    }, 0);
});
1 голос
/ 25 ноября 2013

Это сложная проблема, чтобы получить «право». Вы можете попытаться скрыть нижний колонтитул на фокусе элемента ввода и показать размытие, но это не всегда надежно в iOS. Время от времени (скажем, один раз в десять на моем iPhone 4S) событие фокусировки, похоже, не срабатывает (или, может быть, есть условие гонки), и нижний колонтитул не скрывается.

После долгих проб и ошибок я нашел это интересное решение:

<head>
    ...various JS and CSS imports...
    <script type="text/javascript">
        document.write( '<style>#footer{visibility:hidden}@media(min-height:' + ($( window ).height() - 10) + 'px){#footer{visibility:visible}}</style>' );
    </script>
</head>

По сути: используйте JavaScript для определения высоты окна устройства, затем динамически создайте медиазапрос CSS, чтобы скрыть нижний колонтитул, когда высота окна уменьшается на 10 пикселей. Поскольку открытие клавиатуры изменяет размер экрана браузера, на iOS это никогда не заканчивается. Поскольку он использует движок CSS, а не JavaScript, он намного быстрее и плавнее!

Примечание: я обнаружил, что использование 'visibility: hidden' менее затруднительно, чем 'display: none' или 'position: static', но ваш пробег может отличаться.

1 голос
/ 26 сентября 2013

действительно усердно работал, чтобы найти этот обходной путь, который вкратце ищет события фокусировки и размытия на входах, а также прокрутку для выборочного изменения положения фиксированной полосы, когда события происходят. Это пуленепробиваемый и охватывает все случаи (навигация с помощью <>, прокрутка, кнопка Готово). Примечание id = "nav" - это мой фиксированный div нижнего колонтитула. Вы можете легко перенести это на стандартный js или jquery. Это додзе для тех, кто использует электроинструменты; -)

определить ([ «Додзё / готов», «Додзё / запрос», ], функция (готово, запрос) {

ready(function(){

    /* This addresses the dreaded "fixed footer floating when focusing inputs and keybard is shown" on iphone 
     * 
     */
    if(navigator.userAgent.match(/iPhone/i)){
        var allInputs = query('input,textarea,select');
        var d = document, navEl = "nav";
        allInputs.on('focus', function(el){
             d.getElementById(navEl).style.position = "static";
        });

        var fixFooter = function(){
            if(d.activeElement.tagName == "BODY"){
                d.getElementById(navEl).style.position = "fixed";
            }
        };
        allInputs.on('blur', fixFooter);
        var b = d.body;
        b.addEventListener("touchend", fixFooter );
    }

});

}); // конец определения

0 голосов
/ 16 июня 2016

iOS9 - та же проблема.

TLDR - источник проблемы. Для решения прокрутите вниз

У меня была форма в position:fixed iframe с id = 'subscribe-popup-frame'

Согласно исходному вопросу, при фокусировке ввода iframe будет перемещаться в верхнюю часть документа, а не в верхнюю часть экрана.

Та же проблема не возникала в режиме разработки safari с пользовательским агентом, установленным на idevice. Похоже, что проблема вызвана виртуальной клавиатурой iOS, когда она появляется.

Я получил некоторое представление о том, что происходило, записав в консоли позицию iframe (например, $('#subscribe-popup-frame', window.parent.document).position()), и оттуда я увидел, что iOS, похоже, устанавливает положение элемента на {top: -x, left: 0}, когда виртуальная клавиатура выскочила ( т.е. сфокусирован на элементе ввода).

Таким образом, мое решение состояло в том, чтобы взять этот надоедливый -x, поменять знак и затем использовать jQuery, чтобы добавить эту позицию top обратно в iframe. Если есть лучшее решение, я бы хотел услышать его, но, попробовав дюжину разных подходов, он работал только для меня.

Недостаток: Мне нужно было установить тайм-аут в 500 мс (возможно, меньше будет работать, но я хотел быть в безопасности), чтобы убедиться, что я захватил окончательное значение x после того, как iOS нанесла вред положение элемента. В результате опыт очень отрывистый. , , но по крайней мере это работает

Решение

        var mobileInputReposition = function(){
             //if statement is optional, I wanted to restrict this script to mobile devices where the problem arose
            if(screen.width < 769){
                setTimeout(function(){
                    var parentFrame = $('#subscribe-popup-frame',window.parent.document);
                    var parentFramePosFull = parentFrame.position();
                    var parentFramePosFlip = parentFramePosFull['top'] * -1;
                    parentFrame.css({'position' : 'fixed', 'top' : parentFramePosFlip + 'px'});
                },500);
            }    
        }   

Тогда просто позвоните mobileInputReposition, например, $('your-input-field).focus(function(){}) и $('your-input-field).blur(function(){})

0 голосов
/ 16 января 2016

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

$("#myInput").on("focus", function () {
    $("body").css("position", "fixed");
});

$("#myInput").on("blur", function () {
    $("body").css("position", "static");
});
0 голосов
/ 28 августа 2015

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

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

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

...