How to prevent vertical scroll on swipe left/right

后端 未结 2 1549
遇见更好的自我
遇见更好的自我 2021-02-04 19:06

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

// ang         


        
相关标签:
2条回答
  • 2021-02-04 20:06

    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

    0 讨论(0)
  • 2021-02-04 20:08

    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)

    0 讨论(0)
提交回复
热议问题