web-dev-qa-db-fra.com

Désactiver le défilement dans une application Web iPhone?

Existe-t-il un moyen de désactiver complètement le défilement de pages Web dans une application Web pour iPhone? J'ai essayé de nombreuses choses postées sur google, mais aucune ne semble fonctionner.

Voici ma configuration actuelle d'en-tête:

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/>
<meta name="Apple-mobile-web-app-capable" content="yes"/>

document.body.addEventListener('touchmove', function(e){ e.preventDefault(); });

ne semble pas fonctionner.

57
Stefan Kendall

'self.webView.scrollView.bounces = NO;'

Ajoutez simplement cette ligne dans le 'viewDidLoad' du fichier mainViewController.m de votre application. vous pouvez l'ouvrir dans le Xcode et l'ajouter. 

Cela devrait rendre la page sans rebonds élastiques, permettant ainsi le défilement dans la vue de l'application. 

10
Chait

Passez à l'événement touchstart au lieu de touchmove. Sous Evénements One Finger il est indiqué qu'aucun événement n'est envoyé pendant un panoramique, donc touchmove peut être trop tard.

J'ai ajouté l'auditeur au document, pas au corps.

Exemple:

document.ontouchstart = function(e){ 
    e.preventDefault(); 
}
56
drawnonward
document.addEventListener('touchstart', function (e) {
    e.preventDefault();
});

N'utilisez pas la propriété ontouchmove pour inscrire le gestionnaire d'événements, car vous courez le risque d'écraser un ou plusieurs gestionnaires d'événements existants. Utilisez addEventListener à la place (voir la remarque à propos de IE sur la page MDN).

Notez que le fait d'empêcher la valeur par défaut pour l'événement touchstart sur les window ou document désactive le défilement des zones descendantes.

Pour empêcher le défilement du document tout en laissant tous les autres événements intacts, empêchez par défaut le premier événement touchmove suivant touchstart:

var firstMove;

window.addEventListener('touchstart', function (e) {
    firstMove = true;
});

window.addEventListener('touchmove', function (e) {
    if (firstMove) {
        e.preventDefault();

        firstMove = false;
    }
});

Cela fonctionne parce que Safari mobile utilise le premier mouvement pour déterminer si le corps du document est en train de défiler. Je m'en suis rendu compte en élaborant une solution plus sophistiquée.

Au cas où cela ne fonctionnerait jamais, la solution la plus sophistiquée consiste à inspecter l'élément touchTarget et ses parents et à créer une carte des directions dans laquelle vous pouvez faire défiler l'écran. Utilisez ensuite le premier événement touchmove pour détecter la direction de défilement et voir s’il va faire défiler le document ou l’élément cible (ou l’un des parents de l’élément cible):

var touchTarget,
    touchScreenX,
    touchScreenY,
    conditionParentUntilTrue,
    disableScroll,
    scrollMap;

conditionParentUntilTrue = function (element, condition) {
    var outcome;

    if (element === document.body) {
        return false;
    }

    outcome = condition(element);

    if (outcome) {
        return true;
    } else {
        return conditionParentUntilTrue(element.parentNode, condition);
    }
};

window.addEventListener('touchstart', function (e) {
    touchTarget = e.targetTouches[0].target;
    // a boolean map indicating if the element (or either of element parents, excluding the document.body) can be scrolled to the X direction.
    scrollMap = {}

    scrollMap.left = conditionParentUntilTrue(touchTarget, function (element) {
        return element.scrollLeft > 0;
    });

    scrollMap.top = conditionParentUntilTrue(touchTarget, function (element) {
        return element.scrollTop > 0;
    });

    scrollMap.right = conditionParentUntilTrue(touchTarget, function (element) {
        return element.scrollWidth > element.clientWidth &&
               element.scrollWidth - element.clientWidth > element.scrollLeft;
    });

    scrollMap.bottom =conditionParentUntilTrue(touchTarget, function (element) {
        return element.scrollHeight > element.clientHeight &&
               element.scrollHeight - element.clientHeight > element.scrollTop;
    });

    touchScreenX = e.targetTouches[0].screenX;
    touchScreenY = e.targetTouches[0].screenY;
    disableScroll = false;
});

window.addEventListener('touchmove', function (e) {
    var moveScreenX,
        moveScreenY;

    if (disableScroll) {
        e.preventDefault();

        return;
    }

    moveScreenX = e.targetTouches[0].screenX;
    moveScreenY = e.targetTouches[0].screenY;

    if (
        moveScreenX > touchScreenX && scrollMap.left ||
        moveScreenY < touchScreenY && scrollMap.bottom ||
        moveScreenX < touchScreenX && scrollMap.right ||
        moveScreenY > touchScreenY && scrollMap.top
    ) {
        // You are scrolling either the element or its parent.
        // This will not affect document.body scroll.
    } else {
        // This will affect document.body scroll.

        e.preventDefault();

        disableScroll = true;
    }
});

Cela s'explique par le fait que Safari mobile utilise le premier déplacement tactile pour déterminer si le corps du document est en train de défiler ou l'élément (ou l'un des parents de l'élément cible) et s'en tient à cette décision.

15
Gajus

Si vous utilisez jquery 1.7+, cela fonctionne bien:

$("donotscrollme").on("touchmove", false);
13
Rob Lauer

Cela devrait marcher. Plus de zones grises en haut ou en bas :)

<script type="text/javascript">
   function blockMove() {
      event.preventDefault() ;
}
</script>

<body ontouchmove="blockMove()">

Mais cela désactive également les zones de défilement. Si vous souhaitez conserver vos zones de défilement tout en supprimant l’effet élastique en haut et en bas, voir ici: https://github.com/joelambert/ScrollFix .

12
kaleazy

Désactiver: 

document.ontouchstart = function(e){ e.preventDefault(); }

Activer:

document.ontouchstart = function(e){ return true; }
10
Brynner Ferreira

La page doit être lancée à partir de l'écran d'accueil pour que la balise méta fonctionne.

4
Freebie
document.ontouchmove = function(e){ 
    e.preventDefault(); 
}

c’est en fait le meilleur choix que j’ai découvert, car il vous permet de toujours exploiter les champs de saisie et de faire glisser des objets à l’aide de jQuery UI déplaçable, mais empêche le défilement de la page.

1
Josh Bedo

J'ai essayé les réponses ci-dessus et en particulier celles de Gajus mais aucune ne fonctionne. Finalement, j'ai trouvé la réponse ci-dessous pour résoudre le problème, de sorte que seul le corps principal ne défile pas mais que les autres sections de défilement de l'application Web fonctionnent correctement. Il vous suffit de définir la position de votre corps: 

body {

height: 100%;
overflow: hidden;
width: 100%;
position: fixed;
}
0
TheeBen