Ошибка Mobile Safari на кнопке с фиксированным положением после программного изменения scrollTop?

Я почти сделал веб-страницу, но в Mobile Safari (iPhone и iPad iOS 5.0.1) есть одна ошибка с двумя кнопками, которые закреплены в верхнем и нижнем правом углах.

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

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

Что я заметил, так это то, что после программной прокрутки, если вы нажмете чуть ниже ВЕРХНЕЙ кнопки, вы увидите выделение, как если бы вы нажали НИЖНЮЮ кнопку, и действие нижней кнопки обрабатывается, что говорит мне об ошибке, что при прокрутке программно кнопка фиксированного положения по-прежнему перемещается вместе с остальной частью страницы и не возвращается в свое фиксированное положение до тех пор, пока не будет выполнена фактическая сенсорная прокрутка....

Кто-нибудь знает способ обойти это..?

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

http://www.tsdexter.com/ceos

Спасибо за помощь.

Томас

(также, если вы можете указать мне, где я могу отправить сообщение об ошибке в Apple, это тоже было бы хорошо, если только оно еще не было)

РЕДАКТИРОВАТЬ: просто нажмите любую из стрелок отправки, вам не нужно вводить заработную плату / оклад, по умолчанию

РЕДАКТИРОВАТЬ 2: Вот более простой пример, показывающий ту же проблему.

http://www.tsdexter.com/MobileSafariFixedPosBug.html

РЕДАКТИРОВАТЬ 3: Об ошибке сообщили в Apple


person tsdexter    schedule 06.01.2012    source источник
comment
Есть ли способ найти проблему в системе отслеживания ошибок Apple (даже если мне нужно зарегистрироваться для этого), чтобы узнать о текущем статусе ошибки?   -  person thomastiger    schedule 24.04.2012
comment
@tsdexter, можете ли вы опубликовать URL-адрес этой ошибки, о которой вы сообщили, на сайте сообщений об ошибках Apple?   -  person Smccullough    schedule 30.05.2012
comment
@Smccullough, репортер об ошибках Apple, по какой-то причине больше ничего не показывает в моей учетной записи? Это даже не отображается в закрытых ошибках.   -  person tsdexter    schedule 06.06.2012
comment
@tsdexter Очень странно, возможно, я тоже зарегистрирую ошибку. Две жалобы лучше, чем одна. Я опубликую ссылку, как только получу ее там.   -  person Smccullough    schedule 06.06.2012
comment
+1, так как этот вопрос помог мне решить безумную проблему, идентичную тому, как вы описываете   -  person jim tollan    schedule 07.12.2012


Ответы (11)


Я обошел это, добавив 101% высокий div, а затем (почти) сразу удалив его.

Пытаться:

<style>
.iosfix {
  height: 101%;
  overflow: hidden;
}
</style>

и когда вы прокручиваете:

window.scrollTo(0, _NEW_SCROLLTOP_);
$('body').append($('<div></div>').addClass('iosfix'));
setTimeout(function() {
  $('.iosfix').remove();
}, 500);

Он также работает с jQuery.scrollTo.

См. пример здесь.

person Chad Smith    schedule 03.05.2012
comment
подтверждая, что это действительно имеет небольшое мерцание. Кажется менее заметным, чем принятый ответ. - person chris; 15.05.2012
comment
Спасибо, мне это тоже помогло. Мой отлично работает с тайм-аутом 0 мс, и тогда у него нет мерцания. stackoverflow.com/a/11478853/43217 - person mckamey; 14.07.2012
comment
Этот ответ превосходен. Нет мерцания. Именно то, что мне было нужно. Спасибо. - person kukipei; 31.08.2012
comment
Этот ответ работает лучше для меня, поэтому я принимаю его вместо этого. - person tsdexter; 18.01.2013

Мы также столкнулись с этой ошибкой в ​​2 разных приложениях для iPad. Для нас лучшим решением было временно удалить фиксированную позицию из фиксированного элемента после завершения анимированной прокрутки, а затем использовать window.scroll с вертикальным значением, которое мы только что выполнили. прокрутите, затем, наконец, повторно примените стиль с фиксированной позицией. Это вызывает очень незначительное всплеск, поскольку ipad повторно отображает элемент, но это предпочтительнее, чем ошибка.

var $fixedElement = $('#fixedNavigation');
var topScrollTarget = 300;
$("html:not(:animated),body:not(:animated)").stop().animate({ scrollTop: topScrollTarget }, 500, "swing", function(evt) {
    $fixedElement.css({ "position": "relative" });
    window.scroll(0, topScrollTarget );
    $fixedElement.css({ "position": "fixed" });
});
person Dominic Warren    schedule 21.03.2012
comment
Спасибо за комментарий. Мне больше не нужен этот функционал. Однако, если у меня будет время, я протестирую его на странице, для которой он мне нужен, и посмотрю, работает ли он там. Еще раз спасибо! - person tsdexter; 22.03.2012
comment
Спасибо за решение! Вспышка довольно заметна в моем приложении, но она помогает. - person Joel Arnold; 02.04.2012
comment
Это решение работает и для меня. Если вы используете jquery mobile, ваша позиция определяется в классах, поэтому замените position: fixed на position:, чтобы она не была зафиксирована навсегда. - person Lee Crossley; 15.04.2012
comment
Этот обходной путь не будет работать для всех макетов. Если это не работает на вашем макете, попробуйте другие ответы на этой странице или небольшие варианты. В моем случае изменение ширины тела помогло. - person Ed Kirk; 09.07.2012

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

Сначала я попытался добавить 1 пиксель к ширине фиксированных элементов и удалить его. Это вызвало повторный рендеринг, но повторно визуализированные элементы стали неправильно выровнены с элементами без повторного рендеринга — я подозреваю, что это еще один результат этой ошибки iOS. Ответ заключался в том, чтобы просто добавить к ширине тела и снова вычесть (или установить авто), т.е.:

//jQuery will calculate the current width and then +1 to this and set it
$('body').css('width', '+=1');

//Remove width css
setTimeout(function() {
  $('body').css('width', '');
}, 1);

Если вы не используете jquery, вам нужно будет получить текущую ширину тела + 1 пиксель, а затем установить ширину.

person Ed Kirk    schedule 09.07.2012
comment
+1 это помогло мне больше всего - из-за этого я ходил по кругу буквально ДНИ!! - person jim tollan; 07.12.2012
comment
Ага! Это также помогло мне после двух часов поиска. Tx Ed! - person Haje; 09.12.2013

Вот мое решение, если, как и я, ни одно из предыдущих решений не работает для вас.

Хитрость заключается в следующем:

  • Сделайте свою прокрутку (Animate или scrollTo и т. д.)
  • Сразу после прокрутки position:absolute ваших фиксированных элементов
  • В событии touchmove восстановить позицию: исправлено

Вот пример:

  $('body').animate({
       scrollTop: newPos}, 1000, 'jswing', function () {
          $('header').css({position:'absolute', top:newPos});
  });

  $(document).bind('touchmove',function(){
       $('header').css({position:'fixed', top:'0px'});
  });   

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

person Stephane Brillant    schedule 03.08.2012

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

    var d = document.createElement("div");
    d.style.height = "101%";
    d.style.overflow = "hidden";
    document.body.appendChild(d);
    window.scrollTo(0, scrollToM);
    setTimeout(function() {
        d.parentNode.removeChild(d);
    }, 10);
person httpete    schedule 16.05.2012
comment
Спасибо! Я немного уменьшил ваш ответ (также без мерцания), и обе половины можно запустить подряд: - person mckamey; 14.07.2012


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

Пример:

$('body, html')
    .animate({scrollTop: 0})
    .scrollTop(0);
person Luca De Angelis    schedule 11.01.2012
comment
У вас есть пример такой работы? Я не могу заставить его работать ни на самом сайте, который я создаю, ни на этой странице отчета об ошибке, которую я сделал. Пожалуйста, посмотрите страницу, я добавил ваше исправление, и все еще ничего. (возможно, ваше исправление работает, потому что вы прокручиваете до 0, то есть вы вообще не прокручиваете?) tsdexter.com/MobileSafariFixedPosBug.html - person tsdexter; 13.01.2012
comment
фиксированный добавляется в строке 34 исходного кода. - person tsdexter; 13.01.2012
comment
Да, похоже, это исправляет рендеринг страницы, которая у нас была, но не триггеры кнопок, которые остаются в старом положении. Я обнаружил, что если вы это сделаете: $('body, html') .animate({scrollTop: 0}, function(){ $element.css('display', 'none'); setTimeout(function() { $element.css('display', 'block'); }, 0); }); вы сможете увидеть, где на самом деле находится $element.. - person Luca De Angelis; 16.01.2012

У меня была такая же проблема с iOS5 и JQueryMobile. Фиксированный верхний и нижний колонтитулы. Расширяемый контент, и внезапно у меня появился призрачный нижний колонтитул, который можно было увидеть, но нельзя было потрогать. У меня была небольшая проблема с прямым изменением положения на абсолютное, а затем возвращение к работе. Казалось, что это срабатывало только время от времени. В итоге я использовал это.

        $(myFixedFooter).css("position", "relative").hide(0, function () {
            $(this).show(0).css("position", "");
        });

Это вызывающе создает «вспышку», поскольку нижний колонтитул делает свое дело. Однако я обнаружил, что около 98% времени нижний колонтитул оставался внизу страницы. Все другие обходные пути и настройки, которые я нашел и попробовал, не всегда оставляли нижний колонтитул внизу или они не решали проблему в первую очередь.

Надеюсь, Apple скоро исправит.

person JDubDev    schedule 19.04.2012
comment
Большое спасибо, это единственное исправление, которое сработало для меня! :-) - person DominikGuzei; 12.10.2013

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

Я создал тестовый пример и загрузил файл сюда (если вы просматриваете его в браузере, отличном от iPhone, сделайте окно маленьким по вертикали, чтобы увидеть правильное поведение):

http://www.misterpeachy.com/index_test.html

Я понял, что индексное меню прокручивалось вместе с текстом (хотя видимое меню не двигалось) после того, как я нажал B, а затем снова нажал B. Вместо прокрутки до B (практически не двигаясь), он прокручивается до D.

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

person Cliff Harris    schedule 23.02.2012
comment
Я сообщил об этом как об ошибке в Apple, и они ответили, что уже знали об этом. Предположительно это означает, что исправление появится в более поздней версии iOS. - person Cliff Harris; 01.03.2012
comment
Извините за задержку. Добавление JavaScript для прокрутки страницы не сработает. Прокрутка JavaScript не приводит к правильному повторному отображению позиции, только реальная физическая прокрутка. Я даже пытался запрограммировать событие касания, имитирующее прокрутку пальцем, но оно все равно не сработало. К сожалению, я думаю, что нам придется подождать Apple в этом вопросе. Хотя у Доминика Уоррена выше, похоже, есть обходной путь (я не пробовал, так как он мне больше не нужен) - person tsdexter; 22.03.2012
comment
Я добавил код JavaScript, обнаруживающий поднятие пальца, но выполнявшийся ДО прокрутки, поэтому он не работал. - person Cliff Harris; 30.07.2012

В случае, если это может помочь кому-то:

У меня была точно такая же проблема, и мой код выглядел примерно так (это одностраничное веб-приложение):

window.scrollTo(0,0);
$('section.current').removeClass('current');
$(target).addClass('current');

Я часами пробовал все (дивы высоты 101%, изменение типа позиции...), но, наконец, последнее предложение, описанное на Device-Bugs спас положение. В моем случае это был просто вопрос прокрутки, когда div не отображаются:

$('section.current').removeClass('current');
window.scrollTo(0,0);
$(target).addClass('current');
person Romain    schedule 20.06.2012

Еще один вариант решения — увеличить размер документа по ширине на 1 пиксель, а затем сразу же отменить это действие. Преимущество этого заключается в том, что больше не создаются элементы, и нет никакого мерцания, которое я испытал.

https://stackoverflow.com/a/11479118/43217

person mckamey    schedule 13.07.2012

Пример кода

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'});
    });
}
person ShibinRagh    schedule 13.03.2014