How to prevent vertical scroll on swipe left/right
Asked Answered
T

2

6

When I try to swipe left/right my app content also scrolls vertically creating messy UX. Is there a way to prevent it?

This is how I handle swipe

// angular directive
link: function(scope, element, attrs) {
        $ionicGesture.on('swiperight', function(){console.log("swiped");}, element );
}
Take answered 7/12, 2014 at 17:15 Comment(2)
please check reformulated answer, and provide feedback when able...Fluorosis
@Fluorosis sorry, i have no way/time of checking this anymore, i dont even use ionic now, let the community deal with it, there are quite a few interested people.Take
F
5

FOREWORD: This solution was entirely rephrased after ensuring compatibility with both ios and android environments; comments below may no longer apply; any feedback is welcome.


YES, there is a way to prevent app content from scrolling when you swipe horizontally: by combining an angularjs tapDetector directive with ionic $ionicScrollDelegate service.

We will also need to detect the swipe using very fast dom events detection (mousedown/touchstart, mousemove/touchmove, mouseup/touchend); it is necessary because $ionicGesture event listener detects the swipe after the scroll has been done: detection for swipe in ionic is to slow for our purpose.


The tapDetector directive is placed on body like so:

<body ng-controller="MyCtrl" tap-detector>

And here is the code for the directive:

.directive('tapDetector',function($ionicGesture,$ionicScrollDelegate){
  return{
    restrict:'EA',
    link:function(scope,element){
      var startX,startY,isDown=false;
      element.bind("mousedown touchstart", function(e){
        e=(e.touches)?e.touches[0]:e;//e.touches[0] is for ios
        startX = e.clientX;
        startY = e.clientY;
        isDown=true;
        //console.log("mousedown",startX,startY);
      });

      element.bind("mousemove touchmove", function(e){
        e=(e.touches)?e.touches[0]:e;//e.touches[0] is for ios
        if(isDown){
          var deltaX = Math.abs(e.clientX - startX);
                var deltaY = Math.abs(e.clientY - startY);

          if(deltaX > deltaY) {
          //console.log("horizontal move");
            $ionicScrollDelegate.$getByHandle('mainScroll').freezeScroll(true);
            }
        }
      });

      element.bind("mouseup touchend", function(e){
        isDown=false;
        $ionicScrollDelegate.$getByHandle('mainScroll').freezeScroll(false);
        //console.log("mouseup touchend");
      });
    }
  }
})

When you touch the screen (preparation for swipe), the coordinates of touch are set (startX, startY) and isDown is set to true.

When you start swiping, we need to determine whether swipe is horizontal or vertical. We are only interested in horizontal swipes:

var deltaX = Math.abs(e.clientX - startX);
var deltaY = Math.abs(e.clientY - startY);

deltaX is the difference (delta) between original X and current X; deltaY is the difference (delta) between original Y and current Y;

if (deltaX > deltaY)

We got an horizontal swipe!

Now the swipe has been detected fast enough, all that is left to be done is to dynamically prevent the scroll:

$ionicScrollDelegate.$getByHandle('mainScroll').freezeScroll(true);

and in the HTML: <ion-content delegate-handle="mainScroll">


After scroll is complete, we must un-freeze (thaw?) the scroll:

element.bind("mouseup touchend", function(e){
                    isDown=false;
                    $ionicScrollDelegate.$getByHandle('mainScroll').freezeScroll(false);
                });

This was tested with iPad 2 and Android Galaxy S4


Almost forgot: here is a working pen (courtesy of sMr)

Fluorosis answered 1/4, 2015 at 12:55 Comment(9)
@sMr since you opened a bounty please check this and tell me if it works so i can accept the answer.Take
@Take i tried the answer but it frezee the content while swiping.. so lets wait for another answers until the last day of bountySneaky
@sMr yes, I put an arbitrary delay of 3s before resuming normal scrolling behavior; it can be shortened as you wish, though; please specify what exact behavior you are expecting: right now vertical scrolling is prevented after a swipe has been triggered: isn't it what was required?Fluorosis
@Fluorosis first of all i am using an ion-list and each ion-item in the list has swipe left and right gestures. When you swipe left or right with not an exact horizantal line before swipe event being triggered the ion-list scrolls this makes a little vertical scroll befere freeze itSneaky
ok, I understand. You would need to stop the scroll just before the swipe, otherwise there is still some scrolling happening, correct?Fluorosis
@Fluorosis yes exactly. by the way i made a pen that desribes my problem codepen.io/anon/pen/JoVxqj.Sneaky
ok, thanks, got another idea, will try it in your pen (see updated answer)Fluorosis
@sMr thanks for the pen you provided. I now provided what I believe is a working solution (see edit); follow the link in the updated answer, as I forked your pen, the pen url is differentFluorosis
Let us continue this discussion in chat.Sneaky
T
0

Currently there is no API from ionic team to do that, but i temporary made a monkey patch and feature request. https://github.com/driftyco/ionic/issues/2703

Take answered 11/12, 2014 at 19:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.