ionic-team / ionic-v1

The repo for Ionic 1.x. For the latest version of Ionic, please see https://github.com/ionic-team/ionic
Other
193 stars 187 forks source link

ion-reorder in ion-list drags whole screen rather than item #224

Open jgw96 opened 7 years ago

jgw96 commented 7 years ago

From @LucasMcL on March 12, 2017 20:59

Ionic version: (check one with "x") [X] 1.x [ ] 2.x

I'm submitting a ... (check one with "x") [X] bug report [ ] feature request [ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/

Current behavior: The reordering functionality built directly into via is not working properly on my android phone. When I press and hold the reorder button, then move up or down, it scrolls the whole screen rather than the individual item. Thus, you can't actually reorder the item.

Expected behavior: I expect the screen to not move unless the item I'm scrolling gets near the top or bottom, at which point the screen should scroll in that direction.

Steps to reproduce: I've included a codepen with code similar to my project. It seems to work in code pen, but when I pull it down and run it on my phone, it recreates the issue. I've also included a gif that shows the issue. My phone is a Moto X Pure Edition running android operating system 6.0.

Related code: https://media.giphy.com/media/xUPGcCT4rHhzgVKzJK/giphy.gif http://codepen.io/LucasMcL/pen/ryemMJ

Other information:

Similar post in forums: https://forum.ionicframework.com/t/ionic-reorder-poor-responsiveness-on-android-phone/81886 My list with delete and reorder buttons is very similar to the official ionic example on codepen: https://codepen.io/ionic/pen/JsHjf.

Things I've tried: -Reducing the size of the objects in the array that comprises the -Showing just the reorder button and not delete at the same time -Using collection-repeat

Ionic info: (run ionic info from a terminal/cmd prompt and paste output below):

******************************************************
 Dependency warning - for the CLI to run correctly,
 it is highly recommended to install/upgrade the following:

 Install ios-sim to deploy iOS applications.`npm install -g ios-sim` (may require sudo)
 Install ios-deploy to deploy iOS applications to devices.  `npm install -g ios-deploy` (may require sudo)

******************************************************

Your system information:

Cordova CLI: 6.5.0
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
ios-deploy version: Not installed
ios-sim version: Not installed
OS: OS X El Capitan
Node Version: v7.4.0
Xcode version: Not installed

Copied from original issue: driftyco/ionic#10747

KamranKawish commented 7 years ago

Have you found any solutions for the problem, I seem to be having the same problem

LucasMcL commented 7 years ago

I have not. I've had this issue for weeks and have been unable to solve it. I'm hoping the good folks at Ionic are able to help out.

KamranKawish commented 7 years ago

It seems to cause this problem when I use ion-scroll. On a normal ion-content with scroll it works like it is supposed to

KamranKawish commented 7 years ago

here is how solved the problem. create a css rule ".noscroll { pointer-events: none; }" and then use ng-class to apply this rule to your ion-scroll with the same boolean you use for show-reorder. I hope it helps

gylippus commented 7 years ago

@KamranKawish can you clarify the css that you are describing? Not sure I'm following the syntax you use.

KamranKawish commented 7 years ago

@gylippus Sorry there was a typo mistake, I updated my comment.

LucasMcL commented 7 years ago

@KamranKawish My ion-reorder isn't in an ion-scroll; it is inside a normal ion-content. In fact, it is almost identical to the official example here: https://codepen.io/ionic/pen/JsHjf. I will try manually toggling the scroll with a boolean, though.

gylippus commented 7 years ago

@LucasMcL I tried what was suggested using css to select and apply pointer-events: none to the ion-scroll when the reorder was active. I didn't help for me.

LucasMcL commented 7 years ago

@KamranKawish that worked for me! Thanks so much! I modified it a little bit. Here's my code:

HTML:

<ion-content class="padding" ng-class="{noscroll: reordering}">

...

    <ion-list show-reorder="editMode", show-delete="editMode">

      <ion-item ng-repeat="item in tracks">
        <ion-delete-button class="ion-minus-circled" ng-click="onItemDelete(item)">
        </ion-delete-button>
        <h3>{{item.track.name}}</h3>
        <p>{{item.track.artists[0].name}} • {{item.track.album.name}}</p>
        <ion-reorder-button class="ion-navicon" on-reorder="onItemMove(item, $fromIndex, 
          $toIndex)"
          on-touch="onReorderButtonTouch()"
          on-release="onReorderButtonRelease()"></ion-reorder-button>
      </ion-item>

    </ion-list>

JS: ` $scope.onReorderButtonTouch = function() { $scope.reordering = true }

$scope.onReorderButtonRelease = function() { $scope.reordering = false }`

CSS: .noscroll { pointer-events: none; }

I needed to still be able to scroll when in edit mode. I just needed it to not scroll specifically when the user was reordering an item. So, I toggle a variable on touch and on release of the reorder button itself. I use that variable to apply the CSS that @KamranKawish provided.

gylippus commented 7 years ago

@LucasMcL where did you attach the onReorderButtonTouch and onReorderButtonRelease in the HTML?

LucasMcL commented 7 years ago

@gylippus Fair question. I've updated my comment with some more code. Maybe too much code. But there you go. Towards the bottom, you can see that the onReorderButtonTouch and onReorderButtonRelease functions are called in the on-touch and on-release directives of the actual ion-reorder button.

gylippus commented 7 years ago

@LucasMcL thanks for that. I do see a pretty solid improvement in the browser while testing, but I'm still hitting issues where the dragging item is just staying fixed to the top or bottom causing the whole list to continuously scroll on an actual Android device. I'm trying to look into some of the thresholds for boundaries at the moment.

LucasMcL commented 7 years ago

@gylippus let me know what you find. It's working for me, but I do find that it's a little bit hard to control the rate at which its scrolls. It often scrolls REALLY fast when the reordered item is at the top or bottom of the screen. I would be interested in learning how to adjust those thresholds a little.

freddiescott commented 7 years ago

Thank you @LucasMcL , this worked for me !

KamranKawish commented 7 years ago

you can use $ionicScrollDelegate.getScrollView().options.scrollingY=false; in you touch and release functions but beware that it will completely freeze the scroll and will not scroll up/down if your item has reached the top/bottom of the page

KamranKawish commented 7 years ago

$ionicScrollDelegate.$getByHandle('handleName').getScrollView().options.scrollingY if you are using a delegate handle

pfiaux commented 7 years ago

It looks like the problem comes from the listview drag implementation (which tries to scroll and runs call backs even if scroll is disabled (trouble some with native scroll): https://github.com/ionic-team/ionic-v1/blob/fded25c17864ac9bc37aedd9c1abf2295f4dca03/js/views/listView.js#L278

if (e.gesture.deltaY < 0 && pixelsPastTop > 0 && scrollY > 0) {
  this.scrollView.scrollBy(null, -pixelsPastTop);
  //Trigger another drag so the scrolling keeps going
  ionic.requestAnimationFrame(function() {
    self.drag(e);
  });
}
if (e.gesture.deltaY > 0 && pixelsPastBottom > 0) {
  if (scrollY < this.scrollView.getScrollMax().top) {
    this.scrollView.scrollBy(null, pixelsPastBottom);
    //Trigger another drag so the scrolling keeps going
    ionic.requestAnimationFrame(function() {
      self.drag(e);
    });
  }
}

basically if you go past the edge you need to keep scrolling, so it calls itself with the event.

However the events are never marked as stale and there's no way to reset this scrolling until it his the top/bottom. It's not infinite recursion but it's missing a bottom condition (drag is no longer past bottom or top).

pfiaux commented 7 years ago

I replaced the code above and I can now stop scrolling:

      if (!e.stale) {
        if (pixelsPastBottom <= 0 && pixelsPastTop <= 0) {
          this._currentDrag.overScrollPixels = 0;
        }
        else if (e.gesture.deltaY < 0 && pixelsPastTop > 0 && scrollY > 0) {
          this._currentDrag.overScrollPixels = -pixelsPastTop;
        }
        else if (e.gesture.deltaY > 0 && pixelsPastBottom > 0 && scrollY < this.scrollView.getScrollMax().top) {
          this._currentDrag.overScrollPixels = pixelsPastBottom;
        }
      }
      // Don't process this event again!
      e.stale = true;

      if (this._currentDrag.overScrollPixels !== 0) {
        this.scrollView.scrollBy(null, this._currentDrag.overScrollPixels);

        //Trigger another drag so the scrolling keeps going
        // until overScrollPixels hits 0
        setTimeout(function() {
          ionic.requestAnimationFrame(function() {
            self.drag(e);
          });
        }, 10);
      }

It's still not perfect and can scroll too quickly to the top/bottom (before a drag without scroll event can be handled). Possible improvements: