djett41 / ionic-scroll-sista

An Ionic plugin that hides the header/tabs while scrolling
MIT License
125 stars 38 forks source link

Scroll goes to top when you change between views #14

Open CescZafra opened 9 years ago

CescZafra commented 9 years ago

I have two consecutive views with using scroll-sista. And when I go back navigating (A -> B -> A) the scroll-sista forces my view to scroll top. I know this behavior is forced here:

/**
* Scroll to the top when entering to reset then scrollView scrollTop. (prevents jumping)
*/
$scope.$parent.$on('$ionicView.beforeEnter', function () {
  if (scrollDelegate) {
     scrollDelegate.scrollTop();
  }
});

I tried to avoid it deleting this lines and just got what you say in your comment. But, is there any way to make it work preserving the scroll and avoiding the jump effect?

Thank you in advance.

CescZafra commented 9 years ago

I think I found a solution but I'm not very proud of it: Firstly you need to add a service:

.factory('ScrollPositions',function() {

  var scrollPositions = {};
  return {
    set: function(state_name, scrollPos){
      scrollPositions[state_name]=scrollPos;
    },
    get: function(state_name){
      return scrollPositions[state_name];
    }
  }
});

(I think you only need the object declaration inside the service to be able to use my solution, because you can do the other functions directly in the directive, but I don't know..)

Then you only have to add this to your directive:

//in every state change you save the state name (it could be better to save the view or more information because it could be different views in the same state) and the scroll point
$scope.$parent.$on('$stateChangeStart', function(){
  ScrollPositions.set($state.current.name, $ionicScrollDelegate.getScrollPosition());
})

// then, in state change succes, you save this scroll point in a $scope var
$scope.$parent.$on('$stateChangeSuccess', function(){
  $scope.offset = ScrollPositions.get($state.current.name);
})

Finally in scroll function:

/**
* Called onScroll.  computes coordinates based on scroll position and translates accordingly
*/
$element.bind('scroll', function (e) {
  if (isNavBarTransitioning) {
    return;
  }

  var duration = 0;
  var scrollTop = e.detail.scrollTop;

  //Here we set the point we saved before as "starting" scroll point but then, since the prevScrollTop is dinamically managed, we set as undefined our saved scroll point and leave the prevScrollTop act as default
  y = scrollTop >= 0 ? Math.min(defaultEnd, Math.max(0, y + scrollTop - ($scope.offset && $scope.offset.top && $scope.offset.top>prevScrollTop ? $scope.offset.top : prevScrollTop))) : 0;

  //if we are at the bottom, animate the header/tabs back in
  if (scrollView.getScrollMax().top - scrollTop <= contentTop) {
    y = 0;
    duration = defaultDuration;
  }

  prevScrollTop = scrollTop;
  $scope.offset=undefined;

  //if previous and current y are the same, no need to continue
  if (prevY === y) {
    return;
  }

  prevY = y;

  translateElements(y, duration);
});

Hope to hear from you soon.

wodCZ commented 9 years ago

@CescZafra thank you for your workaround. I have updated it a little, because it didn't work fully for me.

My version: https://gist.github.com/wodCZ/ed1a2eb44b001337b6bc

Edit: when leaving view with this version with header visible, it hides & shows header before leaving.