it-swarm.com.de

Wie verhindere ich, dass sich meine feste Navigation so bewegt, wenn die virtuelle Tastatur in Mobile Safari geöffnet wird?

Ich verstehe, dass Mobile Safari eine Menge Fehler in Bezug auf feste Elemente aufweist, aber zum größten Teil habe ich es geschafft, mein Layout korrekt zu gestalten, bis ich der festen Navigation unten eine dringend benötigte Texteingabe hinzugefügt habe. Wenn sich der Benutzer auf das Texteingabeelement konzentriert und die virtuelle Tastatur angezeigt wird, springt meine Navigation, die ansonsten immer am unteren Rand der Seite festgelegt ist, zu einer wirklich seltsamen Stelle in der Mitte der Seite.

enter image description here

Ich würde diesem Beitrag einen Teil meines Codes hinzufügen, wäre mir aber nicht sicher, wo ich anfangen soll. Diese Navigation ist unten fixiert und links und unten 0 und 100% breit positioniert. Von dort weiß ich nicht, was los ist, ich kann nur davon ausgehen, dass es sich um einen mobilen Safari-Bug handelt.

Es scheint auch seine feste Position zu verlieren und relativ zu werden, nur wenn das Texteingabeelement aktiviert und die virtuelle Tastatur geöffnet ist.

47
Eric

http://dansajin.com/2012/12/07/fix-position-fixed/ Dies ist eine der vorgeschlagenen Lösungen. Scheint einen Versuch wert.

Kurz gesagt: Setze fixed Elemente auf position:absolute, wenn eine Eingabe focused ist, und setzen Sie sie zurück, wenn dieses Element blurred ist

.header { 
    position: fixed; 
} 
.footer { 
    position: fixed; 
} 
.fixfixed .header, 
.fixfixed .footer { 
    position: absolute; 
} 

und

if ('ontouchstart' in window) {
    /* cache dom references */ 
    var $body = $('body'); 

    /* bind events */
    $(document)
    .on('focus', 'input', function() {
        $body.addClass('fixfixed');
    })
    .on('blur', 'input', function() {
        $body.removeClass('fixfixed');
    });
}
19
Sujesh Arukil

Die Lösungen auf der Oberseite sind einige Möglichkeiten, das Problem zu beheben, aber ich denke, zusätzliche CSS-Klasse hinzuzufügen oder Moderniz zu verwenden, erschweren die Dinge.

Wenn Sie eine einfachere Lösung wünschen, ist hier ein non-modernizrnon-extra-css aber reines jquery solution und Arbeit auf jedem Gerät und jedem Browser Ich verwende diesen Fix für alle meine Projekte

if ('ontouchstart' in window) {
    $(document).on('focus', 'textarea,input,select', function() {
        $('.navbar.navbar-fixed-top').css('position', 'absolute');
    }).on('blur', 'textarea,input,select', function() {
        $('.navbar.navbar-fixed-top').css('position', '');
    });
}
15
revobtz

Ich hatte ein ähnliches Problem, aber ich fand eine Problemumgehung, indem ich die folgende CSS-Klasse zum body-Element beim Eingabefokus hinzufügte und sie dann beim Unfokus wieder entfernte:

.u-oh {
    overflow: hidden;
    height: 100%;
    width: 100%;
    position: fixed;
}
5
sylowgreen

Ausgehend von dem, was sylowgreen getan hat, besteht der Schlüssel darin, das body bei der Eingabe des input zu korrigieren. Somit:

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

$("#myInput").on("blur", function () {
    $("body").css("position", "static");
});
3
Scott Semyan

Fügen Sie Javascript wie folgt hinzu:

$(function() {
  var $body;
  if ('ontouchstart' in window) {
    $body = $("body");
    document.addEventListener('focusin', function() {
      return $body.addClass("fixfixed");
    });
    return document.addEventListener('focusout', function() {
      $body.removeClass("fixfixed");
      return setTimeout(function() {
        return $(window).scrollLeft(0);
      }, 20);
    });
  }
});

und füge eine Klasse wie diese hinzu:

.fixfixed header{ 
    position: absolute; 
} 

sie können auf diesen Artikel verweisen: http://dansajin.com/2012/12/07/fix-position-fixed/

2
wxy112233

Ich benutze dieses jQuery-Skript:

var focus = 0;
var yourInput = $(".yourInputClass");
yourInput.focusin(function(){
    if(!focus) {
        yourInput.blur();
        $("html, body").scrollTop($(document).height());
        focus = 1;
    }
    if(focus) {
        yourInput.focus();
        focus = 0;
    }
});

Funktioniert perfekt für mich.

1
Edie Johnny

Die Ereignisse focusin und focusout scheinen für dieses Problem besser geeignet zu sein als die Ereignisse focus und blur, da sich die erste Blase bis zum Stammelement erstreckt. Siehe diese Antwort auf SO.

Ich persönlich benutze AngularJS und habe es folgendermaßen implementiert:

$window.document.body.addEventListener('focusin', function(event) {
    var element = event.target;
    var tagName = element.tagName.toLowerCase();
    if(!$rootScope.inputOverlay && (tagName === 'input' || tagName === 'textarea' || tagName === 'select')) {
        $rootScope.$apply(function() {
            $rootScope.inputOverlay = true;
        });
    }
});
$window.document.body.addEventListener('focusout', function() {
    if($rootScope.inputOverlay) {
        $rootScope.$apply(function() {
            $rootScope.inputOverlay = false;
        });
    }
});

Hinweis: Ich führe dieses Skript unter bestimmten Bedingungen aus, wenn es sich um eine mobile Safari handelt.

Ich habe ein ng-class Attribut auf meiner Navigationsleiste:

<div class="navbar navbar-default navbar-fixed-top" ng-class="{'navbar-absolute': inputOverlay}">

mit dem folgenden CSS:

.navbar-absolute {
    position: absolute !important;
}

Sie können mehr über focusinhier und focusouthier lesen.

1
brain_bacon

Ich mag die Lösung oben wirklich. Ich habe es in ein kleines jQuery-Plugin gepackt, damit ich:

  • Legen Sie fest, welcher Elternteil die Klasse erhält
  • Stellen Sie ein, für welche Elemente dies gilt (vergessen Sie nicht "textarea" und "select").
  • Legen Sie den Namen der übergeordneten Klasse fest
  • Lassen Sie es angekettet werden
  • Lassen Sie es mehrmals verwenden

Codebeispiel:

$.fn.mobileFix = function (options) {
    var $parent = $(this),
    $fixedElements = $(options.fixedElements);

    $(document)
    .on('focus', options.inputElements, function(e) {
        $parent.addClass(options.addClass);
    })
    .on('blur', options.inputElements, function(e) {
        $parent.removeClass(options.addClass);

        // Fix for some scenarios where you need to start scrolling
        setTimeout(function() {
            $(document).scrollTop($(document).scrollTop())
        }, 1);
    });

    return this; // Allowing chaining
};

// Only on touch devices
if (Modernizr.touch) {
    $("body").mobileFix({ // Pass parent to apply to
        inputElements: "input,textarea,select", // Pass activation child elements
        addClass: "fixfixed" // Pass class name
    });
}
1
martinedwards

Keine dieser Lösungen hat für mich funktioniert, da mein DOM kompliziert ist und ich dynamische unendliche Bildlaufseiten habe, sodass ich meine eigenen erstellen musste.

Background: Ich verwende eine feste Kopfzeile und ein Element weiter unten, das darunter haftet, sobald der Benutzer so weit nach unten scrollt. Dieses Element hat ein Suchfeld. Außerdem habe ich dynamische Seiten hinzugefügt, während ich vorwärts und rückwärts scrolle.

Problem: Unter iOS scrollte der Browser jedes Mal, wenn der Benutzer auf die Eingabe im festen Element klickte, ganz nach oben. Dies verursachte nicht nur unerwünschtes Verhalten, sondern löste auch das Hinzufügen meiner dynamischen Seite oben auf der Seite aus.

Erwartete Lösung: Kein Bildlauf in iOS (überhaupt kein Bildlauf), wenn der Benutzer auf die Eingabe im Sticky-Element klickt.

Lösung:

     /*Returns a function, that, as long as it continues to be invoked, will not
    be triggered. The function will be called after it stops being called for
    N milliseconds. If `immediate` is passed, trigger the function on the
    leading Edge, instead of the trailing.*/
    function debounce(func, wait, immediate) {
        var timeout;
        return function () {
            var context = this, args = arguments;
            var later = function () {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };

     function is_iOS() {
        var iDevices = [
          'iPad Simulator',
          'iPhone Simulator',
          'iPod Simulator',
          'iPad',
          'iPhone',
          'iPod'
        ];
        while (iDevices.length) {
            if (navigator.platform === iDevices.pop()) { return true; }
        }
        return false;
    }

    $(document).on("scrollstop", debounce(function () {
        //console.log("Stopped scrolling!");
        if (is_iOS()) {
            var yScrollPos = $(document).scrollTop();
            if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
                $('#searchBarDiv').css('position', 'absolute');
                $('#searchBarDiv').css('top', yScrollPos + 50 + 'px'); //50 for fixed header
            }
            else {
                $('#searchBarDiv').css('position', 'inherit');
            }
        }
    },250,true));

    $(document).on("scrollstart", debounce(function () {
        //console.log("Started scrolling!");
        if (is_iOS()) {
            var yScrollPos = $(document).scrollTop();
            if (yScrollPos > 200) { //200 here to offset my fixed header (50px) and top banner (150px)
                $('#searchBarDiv').css('position', 'fixed');
                $('#searchBarDiv').css('width', '100%');
                $('#searchBarDiv').css('top', '50px'); //50 for fixed header
            }
        }
    },250,true));

Anforderungen: JQuery Mobile ist erforderlich, damit die Startsroll- und Stoppscroll-Funktionen funktionieren.

Debounce ist enthalten, um Verzögerungen auszugleichen, die durch das klebrige Element verursacht werden.

Getestet in iOS10.

0
Dima

Testen Sie diesen. Es klappt. Ich teste es einfach.

$(document).on('focus','input', function() {
    setTimeout(function() {
        $('#footer1').css('position', 'absolute');
        $('#header1').css('position', 'absolute');
    }, 0);
});
$(document).on('blur','input', function() {
    setTimeout(function() {
        $('#footer1').css('position', 'fixed');
        $('#header1').css('position', 'fixed');
    }, 800);
});
0
Hesam