Naprawiono pozycjonowanie iOS 5 i wirtualną klawiaturę

138

Mam witrynę mobilną, w której u dołu ekranu jest przypięty element div za pomocą pozycji: fixed. Wszystko działa dobrze w iOS 5 (testuję na iPodzie Touch), dopóki nie wejdę na stronę z formularzem. Kiedy stukam w pole wprowadzania i pojawia się wirtualna klawiatura, nagle zostaje utracone ustalone położenie mojego elementu div. Element div przewija się teraz wraz ze stroną, o ile klawiatura jest widoczna. Po kliknięciu przycisku Gotowe, aby zamknąć klawiaturę, element div powraca do swojej pozycji u dołu ekranu i przestrzega zasady position: fixed.

Czy ktoś jeszcze doświadczył tego rodzaju zachowania? Czy jest to oczekiwane? Dzięki.

jeffc
źródło
Tak, wygląda na to, że Apple nie przemyślał tego tak dobrze dla IOS5. Wszelkie elementy o ustalonej pozycji stają się względne względem strony, gdy tylko pojawi się wirtualna klawiatura. Prawdopodobnie byłoby OK, gdyby elementy powróciły do ​​pozycji absolutnej, ponieważ nie spowodowałoby to zerwania układu. Niestety faktyczne rozmieszczenie tych elementów jest znacznie mniej przewidywalne. Mam dokładnie ten problem z moim stałym nagłówkiem na [ZMIENIONO]. Przewiń stronę w dół, a następnie kliknij pole wyszukiwania i bang ... układ uszkodzony. Próbowałem nawet to naprawić, powracając do absolutnego pozycjonowania na zdarzeniu ostrości, co działa, ale potem przegrałem
John williams
2
Napotkałem ten sam problem. Czy ktoś zgłosił błąd w Apple, aby dowiedzieć się, jak to naprawić? Czy ktoś jeszcze widział to zachowanie w iOS6?
Robert Hui
1
Mam ten sam problem z iOS6.
Redtopia
24
Wydaje się, że ten sam problem nadal istnieje w iOS7!
Ria Weyprecht
5
Wygląda na to, że nie został naprawiony w iOS 8 ...
contactmatt

Odpowiedzi:

49

Miałem ten problem w swojej aplikacji. Oto jak nad tym pracuję:

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

Po prostu przewijam do góry i umieszczam go tam, aby użytkownik iOS nie zauważył, że dzieje się coś dziwnego. Uwzględnij to w wykrywaniu niektórych klientów użytkownika, aby inni użytkownicy nie odczuli tego zachowania.

Nick Retallack
źródło
Dosłownie natknąłem się na ten problem dzisiaj i wydawało się to najbardziej rozsądne, +1.
Daniel,
3
To działa całkiem nieźle. Wzywam to tylko dla urządzeń z iOS: var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
Redtopia
8
Usunąłem również $ (window) .scrollTop (0) ... Nie sądzę, że jest to potrzebne i spowodowało niechciane przewijanie.
Redtopia
1
Lub po prostu, document.body.scrollTop = 0jeśli nie używasz jQuery i celujesz w najnowsze przeglądarki.
Langdon
W przypadku dłuższych formularzy ustawienie opcji $(window).scrollTop(0);może spowodować przeniesienie skoncentrowanego wejścia poza ekran, np. Wejście dalej w dół strony lub jeśli iPhone jest ustawiony pionowo. Lepszym rozwiązaniem jest ustawienie ostrości header.css({position:'absolute',top:window.pageYOffset+'px'});i rozmycie header.css({position:'fixed',top:0});.
robocat
16

Miałem nieco inny problem z iPadem, w którym klawiatura wirtualna wyrzuciła mój widoczny obszar poza ekran. Po tym, jak użytkownik zamknął wirtualną klawiaturę, mój widok był nadal poza ekranem. W moim przypadku zrobiłem coś takiego:

var el = document.getElementById('someInputElement');
function blurInput() {
    window.scrollTo(0, 0);
}
el.addEventListener('blur', blurInput, false);
ds111
źródło
3
Nie pomaga mi :(
Dmitry
@Altaveron. Przykro mi to słyszeć. Dotyczyło to konkretnego problemu, który miałem na urządzeniach z systemem iOS6 i niższych. Od tamtej pory nie wróciłem.
ds111,
14

To jest kod, którego używamy do rozwiązywania problemów z iPadem. Zasadniczo wykrywa rozbieżności między przesunięciem a pozycją przewijania - co oznacza, że ​​`` naprawiono '' nie działa poprawnie.

$(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);
    }
});
Właz
źródło
Pochodzi z wtyczki jquery.timers. Zamiast tego możesz użyć window.setTimeout.
Hatch
wyzwolenie tej samej funkcji w przypadku rozmycia wejścia i ostrości również będzie pomocne.
Blowsie
Geniusz - naprawdę kopie. Również +1 do sugestii @ Blowsie, by użyć skupienia i rozmycia zamiast przewijania.
Skone
12

Elementy o ustalonej pozycji po prostu nie aktualizują swojej pozycji, gdy klawiatura jest podniesiona. Okazało się, że oszukując Safari, by pomyślał, że rozmiar strony zmienił się, elementy zmieniają swoje położenie. Nie jest idealne, ale przynajmniej nie musisz się martwić przełączeniem na „pozycję: absolutna” i samodzielnym śledzeniem zmian.

Poniższy kod po prostu nasłuchuje, kiedy użytkownik prawdopodobnie korzysta z klawiatury (z powodu koncentracji na danych wejściowych) i dopóki nie usłyszy rozmycia, po prostu nasłuchuje wszelkich zdarzeń przewijania, a następnie wykonuje sztuczkę ze zmianą rozmiaru. Jak dotąd wydaje mi się, że działa całkiem nieźle.

    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;
    });
Riley Dutton
źródło
To tak naprawdę nie działało dla mnie na iPadzie. Skończyło się na zmianie pozycji stałej stopki na względną i mam stopkę na dole strony do momentu wykrycia zdarzenia rozmycia wejścia, kiedy zmieniłem pozycję z powrotem na naprawioną.
Akrikos
6
Już nie działa, iOS prawdopodobnie naprawił każdy błąd, który sprawił, że to zadziałało
Kevin
6

Na wypadek, gdyby ktoś trafił na ten wątek, tak jak ja, badając ten problem. Ten wątek okazał się pomocny w stymulowaniu mojego myślenia na ten temat.

To było moje rozwiązanie tego problemu w ostatnim projekcie. Wystarczy zmienić wartość „targetElem” na selektor jQuery, który reprezentuje twój nagłówek.

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

};

Jest trochę opóźnienie w utrzymywaniu poprawki, ponieważ iOS zatrzymuje manipulację DOM podczas przewijania, ale załatwia sprawę ...

Jory Cunningham
źródło
Działa to świetnie do iOS 7. Czy ktoś jeszcze ma problemy z prawidłowym pozycjonowaniem elementu, ale znika?
Rona Kilmer
@RonaKilmer Zmień initna zwykłą funkcję (nie wywołuje się samoczynnie; uruchamia się za wcześnie). Następnie zadzwoń iOSKeyboardFix.init();tuż przed końcem ifinstrukcji.
cfree
@cfree Dzięki, zaimplementowałem to jakiś czas temu, ale to nie mój problem. Jest coś innego. Jeden z moich stałych elementów znika po zmianie położenia. Drugi nie. Nie mogę winić za to poprawki klawiatury, ponieważ nie dzieje się to wszędzie. Nie widziałem, żeby ktokolwiek inny miał ten sam problem, więc będę musiał sięgnąć głębiej.
Rona Kilmer
4

Żadna z innych odpowiedzi na ten błąd, które znalazłem, nie zadziałała. Udało mi się to naprawić po prostu przewijając stronę z powrotem w górę o 34 piksele, ilość mobilnego safari przewija ją w dół. z jQuery:

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

To oczywiście zadziała we wszystkich przeglądarkach, ale zapobiega awariom w iOS.

NealJMD
źródło
4

Ten problem jest naprawdę irytujący.

Połączyłem niektóre z wyżej wymienionych technik i wymyśliłem to:

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

Mam dwa stałe paski nawigacyjne (nagłówek i stopka, używając programu ładującego Twitter). Obaj zachowywali się dziwnie, gdy klawiatura była podniesiona, i dziwnie znowu po jej wyłączeniu.

Z tą czasową / opóźnioną poprawką działa. Wciąż od czasu do czasu znajduję usterkę, ale wydaje się, że wystarczy, aby pokazać ją klientowi.

Daj mi znać, jeśli to zadziała. Jeśli nie, możemy znaleźć coś innego. Dzięki.

uciekł kot
źródło
2
Wydaje się, że nie potrzebujesz tego limitu czasu (przynajmniej działało dobrze dla mnie bez), a jeśli zdarza się to również na wybranych elementach, poza tym to rozwiązanie działa świetnie.
Phillip Gooch,
3

Miałem ten sam problem z iOS7. Dolne stałe elementy zepsułyby mój widok, który nie byłby prawidłowo ustawiony.

Wszystko zaczęło działać, kiedy dodałem ten metatag do mojego html.

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

Część, która spowodowała różnicę, to:

height=device-height

Mam nadzieję, że to komuś pomoże.

pasevin
źródło
Dzięki @pasevin. To rozwiązało mój problem w iOS 9.3.2
stillatmylinux
3

Wziąłem Jory Cunninghamodpowiedź i poprawiłem ją:

W wielu przypadkach szaleje nie tylko jeden element, ale kilka elementów o stałej pozycji, więc w tym przypadku targetElempowinien to być obiekt jQuery zawierający wszystkie ustalone elementy, które chcesz „naprawić”. Ho, wydaje się, że klawiatura iOS znika, jeśli przewijasz ...

Nie trzeba wspominać, że powinieneś użyć tego zdarzenia PO dokumencie DOM readylub tuż przed </body>tagiem zamykającym .

(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');
    }
})();
vsync
źródło
2
@vsync przeprosiny, nie miałem pojęcia, że ​​jesteś „mistrzem kuchni”
Mike
kiedy wybierz, fokus wejścia w tym czasie nagłówek przesuwa się w górę (niewidoczny). Chcę naprawić nagłówek div podczas fokusowania pól wyboru i wejścia. niech mi ktoś pomoże
VK Chikkadamalla
2

Mam rozwiązanie podobne do @NealJMD, z wyjątkiem tego, że moje wykonuje się tylko dla iOS i poprawnie określa przesunięcie przewijania, mierząc scollTop przed i po natywnym przewijaniu klawiatury, a także używając setTimeout, aby umożliwić przewijanie natywne:

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);
}
ChrisWren
źródło
1

Naprawiłem stałą pozycję zawartości głównego układu mojego iPada w ten sposób:

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);
Brett
źródło
To zadziałało dla mnie naprawdę dobrze w skomplikowanym połączeniu okna dialogowego JQUery UI i klawiatury ekranowej, które pozostawiło mój układ w połowie ekranu, gdy okno dialogowe i klawiatura są zamknięte w tym samym czasie, chociaż z kilkoma zmianami: var main = $ (' body div '). first (); ... i ... function mainHeightChanged () {$ (top) .scrollTop (0); }
Awerealis
1
setInterval... naprawdę? lepiej po prostu pozostać przy błędzie niż robić to
vsync
1

Miałem podobny problem do @ ds111 s. Moja witryna została przesunięta w górę przez klawiaturę, ale nie przesunęła się w dół po zamknięciu klawiatury.

Najpierw wypróbowałem rozwiązanie @ ds111, ale miałem dwa inputpola. Oczywiście najpierw klawiatura znika, potem następuje rozmycie (lub coś w tym rodzaju). A więc drugainput był pod klawiaturą, kiedy fokus przełączał się bezpośrednio z jednego wejścia na drugie.

Co więcej, „skok w górę” nie był dla mnie wystarczająco dobry, ponieważ cała strona ma tylko rozmiar iPada. Więc wygładziłem zwój.

Wreszcie musiałem dołączyć detektor zdarzeń do wszystkich wejść, nawet tych, które były obecnie ukryte, stąd plik live .

Podsumowując, mogę wyjaśnić następujący fragment kodu javascript jako: Dołącz następujący detektor zdarzeń rozmycia do bieżącego i wszystkich przyszłych inputoraz textarea(= live): Poczekaj okres karencji (= window.setTimeout(..., 10)) i płynnie przewiń do góry (= animate({scrollTop: 0}, ...)), ale tylko wtedy, gdy „nie ma klawiatury pokazano "(= 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)
})

Należy pamiętać, że okres karencji (= 10) może być zbyt krótki lub klawiatura może być nadal wyświetlana, chociaż nie ma fokusa inputlub textareajest fokus. Oczywiście, jeśli chcesz, aby przewijanie było szybsze lub wolniejsze, możesz dostosować czas trwania (= 400)

Raul Pinto
źródło
1

Naprawdę ciężko pracowaliśmy, aby znaleźć to obejście, które w skrócie polega na wyszukiwaniu zdarzeń ostrości i rozmycia na danych wejściowych oraz przewijaniu w celu wybiórczej zmiany położenia stałego paska, gdy wystąpią zdarzenia. Jest to kuloodporne i obejmuje wszystkie przypadki (nawigacja za pomocą <>, przewijania, przycisku Gotowe). Note id = "nav" to mój element div w stałej stopce. Możesz łatwo przenieść to do standardowego js lub jquery. To dojo dla tych, którzy używają elektronarzędzi ;-)

define (["dojo / ready", "dojo / query",], function (ready, query) {

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

});

}); // koniec zdefiniuj

httpete
źródło
To może być niesamowite ... przenoszenie do jQuery / js i raport zwrotny. Nawiasem mówiąc, rozwiązania w zakresie niszowych języków skryptowych, które wymagają przeniesienia lub dodania niestandardowych narzędzi do projektu, nie będą, jak można było przewidzieć, uznane za uniwersalne.
ericpeters0n
To nie zadziała w każdym przypadku, ponieważ spowoduje to przewinięcie do „statycznej” pozycji elementu, która może być oddalona o wiele mil od pierwotnej pozycji danych wejściowych, zwłaszcza jeśli znajduje się w stałym kontenerze. Jeśli kontener ma overflow:hiddenregułę, w ogóle nie zobaczysz wprowadzonych danych, ponieważ znajduje się poza polem.
James M. Lay,
1

Jest to trudny problem do rozwiązania problemu. Możesz spróbować ukryć stopkę na fokusie elementu wejściowego i pokazać go przy rozmyciu, ale nie zawsze jest to niezawodne w systemie iOS. Co jakiś czas (powiedzmy raz na dziesięć na moim iPhonie 4S) zdarzenie ostrości wydaje się nie uruchamiać (lub może występuje stan wyścigu), a stopka nie jest ukryta.

Po wielu próbach i błędach wpadłem na to interesujące rozwiązanie:

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

Zasadniczo: użyj JavaScript, aby określić wysokość okna urządzenia, a następnie dynamicznie utwórz zapytanie CSS o media, aby ukryć stopkę, gdy wysokość okna zmniejszy się o 10 pikseli. Ponieważ otwarcie klawiatury zmienia rozmiar wyświetlacza przeglądarki, to nigdy nie kończy się niepowodzeniem w systemie iOS. Ponieważ używa silnika CSS zamiast JavaScript, jest też znacznie szybszy i płynniejszy!

Uwaga: znalazłem użycie opcji „widoczność: ukryta” mniej glitchy niż „wyświetlacz: brak” lub „pozycja: statyczna”, ale przebieg może się różnić.

Richard Kennard
źródło
1
Może być konieczne przełączenie między wysokością i szerokością, aby naprawić ten problem zarówno w trybie pionowym, jak i poziomym.
Neil Monroe
1

Pracuje dla mnie

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'});
    });
}
ShibinRagh
źródło
1

W naszym przypadku naprawiłoby się to, gdy tylko użytkownik przewija stronę. To jest poprawka, której używaliśmy do symulacji przewijania blurw dowolnym inputlub textarea:

$(document).on('blur', 'input, textarea', function () {
    setTimeout(function () {
        window.scrollTo(document.body.scrollLeft, document.body.scrollTop);
    }, 0);
});
basarat
źródło
1

Odpowiadam, że nie da się tego zrobić.

Widzę 25 odpowiedzi, ale żadna nie działa w moim przypadku. Dlatego Yahoo i inne strony ukrywają stały nagłówek, gdy klawiatura jest włączona. Bing zamienia całą stronę jako nieprzewijalną (overflow-y: hidden).

Omówione powyżej przypadki są różne, niektóre mają problemy z przewijaniem, inne z ostrością lub rozmyciem. Niektóre mają stałą stopkę lub nagłówek. Nie mogę teraz przetestować każdej kombinacji, ale możesz w końcu zdać sobie sprawę, że nie da się tego zrobić w twoim przypadku.

Szalai Laci
źródło
To nie odpowiada na pytanie.
neofita
4
Tak, ponieważ odpowiedź brzmi, że nie ma rozwiązania.
Szalai Laci
0

Znalazłem to rozwiązanie na Githubie.

https://github.com/Simbul/baker/issues/504#issuecomment-12821392

Upewnij się, że masz przewijalną zawartość.

// put in your .js file
$(window).load(function(){
    window.scrollTo(0, 1);
});

// min-height set for scrollable content
<div id="wrap" style="min-height: 480px">
  // website goes here
</div>

Pasek adresu zwija się jako dodatkowy bonus.

Leigh Mackay
źródło
0

Na wypadek, gdyby ktoś chciał tego spróbować. Mam następujący działający dla mnie na stałej stopce z polem wejściowym w nim.

<script>
    $('document').ready(
        function() {
            if (navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)
                  || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i)) {
                var windowHeight = $(window).height();
                var documentHeight = $(document).height();

                $('#notes').live('focus', function() {
                    if (documentHeight > windowHeight) {
                        $('#controlsContainer').css({
                            position : 'absolute'
                        });
                        $("html, body").animate({
                            scrollTop : $(document).height()
                        }, 1);
                    }
                });
                $('#notes').live('blur', function() {
                    $('#controlsContainer').css({
                        position : 'fixed'
                    });
                    $("html, body").animate({
                        scrollTop : 0
                    }, 1);
                });
            }
        });
</script>
Bernarda
źródło
0

Mam ten sam problem. Ale zdałem sobie sprawę, że stała pozycja jest po prostu opóźniona i nie jest zerwana (przynajmniej dla mnie). Poczekaj 5–10 sekund i zobacz, czy element DIV dostosuje się z powrotem do dołu ekranu. Uważam, że to nie błąd, ale opóźniona odpowiedź, gdy klawiatura jest otwarta.

Philip
źródło
0

Wypróbowałem wszystkie podejścia z tego wątku, ale jeśli nie pomogły, poszły jeszcze gorzej. Ostatecznie postanowiłem zmusić urządzenie do utraty ostrości:

$(<selector to your input field>).focus(function(){
    var $this = $(this);
    if (<user agent target check>) {
        function removeFocus () {
            $(<selector to some different interactive element>).focus();
            $(window).off('resize', removeFocus);
        }
        $(window).on('resize', removeFocus);
    }
});

i działało jak urok i naprawiło mój lepki formularz logowania.

Proszę UWAGA:

  1. Powyższy kod JS służy jedynie do przedstawienia mojego pomysłu, aby wykonać ten fragment kodu, proszę zamienić wartości w nawiasach kątowych (<>) na wartości odpowiednie dla Twojej sytuacji.
  2. Ten kod jest przeznaczony do pracy z jQuery v1.10.2
Anton Boritskiy
źródło
0

Jest to nadal duży błąd dla wszystkich stron HTML z wyższymi modami Bootstrap w iOS 8.3. Żadne z proponowanych powyżej rozwiązań nie zadziałało i po powiększeniu dowolnego pola poniżej zagięcia wysokiego modalu, Mobile Safari i / lub WkWebView przesunie ustalone elementy do miejsca, w którym znajduje się przewijanie treści HTML, pozostawiając je nieprawidłowo wyrównane do miejsca, w którym faktycznie się znajdują rozłożone.

Aby obejść ten błąd, dodaj detektor zdarzeń do dowolnego z modalnych danych wejściowych, takich jak:

$(select.modal).blur(function(){
  $('body').scrollTop(0);
});

Domyślam się, że to działa, ponieważ wymuszenie wysokości przewijania treści HTML ponownie wyrównuje rzeczywisty widok z miejscem, w którym WebView systemu iOS 8 oczekuje, że będzie stała zawartość modalnego div.

deepfirstdesigner
źródło
0

Jeśli ktoś szukał zupełnie innej trasy (np. Nie chcesz nawet przypinać tego elementu div „footer” podczas przewijania, ale chcesz, aby element div pozostawał na dole strony), możesz po prostu ustawić położenie stopki jako krewny.

Oznacza to, że nawet jeśli klawiatura wirtualna pojawi się w przeglądarce mobilnej, stopka pozostanie zakotwiczona na dole strony, nie próbując reagować na pokaz wirtualnej klawiatury ani jej zamknąć.

Oczywiście w Safari wygląda lepiej, jeśli pozycja jest ustalona, ​​a stopka podąża za stroną podczas przewijania w górę lub w dół, ale z powodu tego dziwnego błędu w przeglądarce Chrome przeszliśmy na względną stopkę.

Terry Bu
źródło
0

Żadne z rozwiązań przewijania nie wydawało się działać dla mnie. Zamiast tego zadziałało ustawienie stałej pozycji ciała, gdy użytkownik edytuje tekst, a następnie przywrócenie go do statycznego, gdy użytkownik skończy. Dzięki temu Safari nie będzie przewijać Twoich treści. Możesz to zrobić albo skupiając się / rozmazując element (y) (pokazane poniżej dla pojedynczego elementu, ale może dotyczyć wszystkich danych wejściowych, obszarów tekstowych) lub jeśli użytkownik robi coś, aby rozpocząć edycję, np. Otwarcie okna modalnego, możesz to zrobić na tej akcji (np. modalne otwieranie / zamykanie).

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

$("#myInput").on("blur", function () {
    $("body").css("position", "static");
});
Scott Semyan
źródło
0

iOS9 - ten sam problem.

TLDR - źródło problemu. Aby znaleźć rozwiązanie, przewiń do dołu

Miałem formularz w position:fixedramce iframe z id = 'subscribe-popup-frame'

Zgodnie z pierwotnym pytaniem, przy fokusie wejścia element iframe byłby na górze dokumentu, a nie na górze ekranu.

Ten sam problem nie wystąpił w trybie deweloperskim safari z agentem użytkownika ustawionym na idevice. Wygląda więc na to, że problem jest spowodowany przez wirtualną klawiaturę iOS, gdy się pojawia.

Uzyskałem pewien wgląd w to, co się dzieje, rejestrując przez konsolę pozycję elementu iframe (np. $('#subscribe-popup-frame', window.parent.document).position()) I stamtąd mogłem zobaczyć, jak iOS ustawia pozycję elementu, {top: -x, left: 0}gdy pojawiła się wirtualna klawiatura (tj. Skupiła się na elemencie wejściowym).

Więc moim rozwiązaniem było skorzystanie z tego nieznośnego -x, odwrócenie znaku, a następnie użycie jQuery, aby dodać tę toppozycję z powrotem do iframe. Jeśli istnieje lepsze rozwiązanie, bardzo bym to usłyszał, ale po wypróbowaniu kilkunastu różnych podejść to jedyne, które mi się udało.

Wada: musiałem ustawić limit czasu na 500 ms (może mniej by działało, ale chciałem być bezpieczny), aby upewnić się, że uchwyciłem ostateczną xwartość po tym, jak iOS zrobił psikusa z pozycją elementu. W rezultacie doświadczenie jest bardzo gwałtowne. . . ale przynajmniej działa

Rozwiązanie

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

Następnie zadzwoń mobileInputRepositionna przykład $('your-input-field).focus(function(){})i$('your-input-field).blur(function(){})

martellalex
źródło