/** * Called by CREATOR. */ private ObservableListSavedState(Parcel input) : base(input) { PrevFirstVisiblePosition = input.ReadInt(); PrevFirstVisibleChildHeight = input.ReadInt(); PrevScrolledChildrenHeight = input.ReadInt(); PrevScrollY = input.ReadInt(); ScrollY = input.ReadInt(); ChildrenHeights = new SparseIntArray(); int numOfChildren = input.ReadInt(); if (0 < numOfChildren) { for (int i = 0; i < numOfChildren; i++) { int key = input.ReadInt(); int value = input.ReadInt(); ChildrenHeights.Put(key, value); } } }
protected override void OnScrollChanged(int l, int t, int oldl, int oldt) { base.OnScrollChanged(l, t, oldl, oldt); if (_mCallbacks != null) { if (ChildCount > 0) { int firstVisiblePosition = GetChildAdapterPosition(GetChildAt(0)); int lastVisiblePosition = GetChildAdapterPosition(GetChildAt(ChildCount - 1)); for (int i = firstVisiblePosition, j = 0; i <= lastVisiblePosition; i++, j++) { int childHeight = 0; View child = GetChildAt(j); if (child != null) { if (_mChildrenHeights.IndexOfKey(i) < 0 || (child.Height != _mChildrenHeights.Get(i))) { childHeight = child.Height; } } _mChildrenHeights.Put(i, childHeight); } View firstVisibleChild = GetChildAt(0); if (firstVisibleChild != null) { if (_mPrevFirstVisiblePosition < firstVisiblePosition) { // scroll down int skippedChildrenHeight = 0; if (firstVisiblePosition - _mPrevFirstVisiblePosition != 1) { for (int i = firstVisiblePosition - 1; i > _mPrevFirstVisiblePosition; i--) { if (0 < _mChildrenHeights.IndexOfKey(i)) { skippedChildrenHeight += _mChildrenHeights.Get(i); } else { // Approximate each item's height to the first visible child. // It may be incorrect, but without this, scrollY will be broken // when scrolling from the bottom. skippedChildrenHeight += firstVisibleChild.Height; } } } _mPrevScrolledChildrenHeight += _mPrevFirstVisibleChildHeight + skippedChildrenHeight; _mPrevFirstVisibleChildHeight = firstVisibleChild.Height; } else if (firstVisiblePosition < _mPrevFirstVisiblePosition) { // scroll up int skippedChildrenHeight = 0; if (_mPrevFirstVisiblePosition - firstVisiblePosition != 1) { for (int i = _mPrevFirstVisiblePosition - 1; i > firstVisiblePosition; i--) { if (0 < _mChildrenHeights.IndexOfKey(i)) { skippedChildrenHeight += _mChildrenHeights.Get(i); } else { // Approximate each item's height to the first visible child. // It may be incorrect, but without this, scrollY will be broken // when scrolling from the bottom. skippedChildrenHeight += firstVisibleChild.Height; } } } _mPrevScrolledChildrenHeight -= firstVisibleChild.Height + skippedChildrenHeight; _mPrevFirstVisibleChildHeight = firstVisibleChild.Height; } else if (firstVisiblePosition == 0) { _mPrevFirstVisibleChildHeight = firstVisibleChild.Height; _mPrevScrolledChildrenHeight = 0; } if (_mPrevFirstVisibleChildHeight < 0) { _mPrevFirstVisibleChildHeight = 0; } _mScrollY = _mPrevScrolledChildrenHeight - firstVisibleChild.Top; _mPrevFirstVisiblePosition = firstVisiblePosition; _mCallbacks.OnScrollChanged(_mScrollY, _mFirstScroll, _mDragging); if (_mFirstScroll) { _mFirstScroll = false; } if (_mPrevScrollY < _mScrollY) { //down _mScrollState = ObservableScrollState.Up; } else if (_mScrollY < _mPrevScrollY) { //up _mScrollState = ObservableScrollState.Down; } else { _mScrollState = ObservableScrollState.Stop; } _mPrevScrollY = _mScrollY; } } } }
private void OnScrollChanged() { if (_mCallbacks != null) { if (ChildCount > 0) { int firstVisiblePosition = FirstVisiblePosition; for (int i = FirstVisiblePosition, j = 0; i <= LastVisiblePosition; i++, j++) { if (_mChildrenHeights.IndexOfKey(i) < 0 || GetChildAt(j).Height != _mChildrenHeights.Get(i)) { if (i % GetNumColumnsCompat() == 0) { _mChildrenHeights.Put(i, GetChildAt(j).Height); } } } View firstVisibleChild = GetChildAt(0); if (firstVisibleChild != null) { if (_mPrevFirstVisiblePosition < firstVisiblePosition) { // scroll down int skippedChildrenHeight = 0; if (firstVisiblePosition - _mPrevFirstVisiblePosition != 1) { for (int i = firstVisiblePosition - 1; i > _mPrevFirstVisiblePosition; i--) { if (0 < _mChildrenHeights.IndexOfKey(i)) { skippedChildrenHeight += _mChildrenHeights.Get(i); } } } _mPrevScrolledChildrenHeight += _mPrevFirstVisibleChildHeight + skippedChildrenHeight; _mPrevFirstVisibleChildHeight = firstVisibleChild.Height; } else if (firstVisiblePosition < _mPrevFirstVisiblePosition) { // scroll up int skippedChildrenHeight = 0; if (_mPrevFirstVisiblePosition - firstVisiblePosition != 1) { for (int i = _mPrevFirstVisiblePosition - 1; i > firstVisiblePosition; i--) { if (0 < _mChildrenHeights.IndexOfKey(i)) { skippedChildrenHeight += _mChildrenHeights.Get(i); } } } _mPrevScrolledChildrenHeight -= firstVisibleChild.Height + skippedChildrenHeight; _mPrevFirstVisibleChildHeight = firstVisibleChild.Height; } else if (firstVisiblePosition == 0) { _mPrevFirstVisibleChildHeight = firstVisibleChild.Height; } if (_mPrevFirstVisibleChildHeight < 0) { _mPrevFirstVisibleChildHeight = 0; } _mScrollY = _mPrevScrolledChildrenHeight - firstVisibleChild.Top; _mPrevFirstVisiblePosition = firstVisiblePosition; _mCallbacks.OnScrollChanged(_mScrollY, _mFirstScroll, _mDragging); if (_mFirstScroll) { _mFirstScroll = false; } if (_mPrevScrollY < _mScrollY) { _mScrollState = ObservableScrollState.Up; } else if (_mScrollY < _mPrevScrollY) { _mScrollState = ObservableScrollState.Down; } else { _mScrollState = ObservableScrollState.Stop; } _mPrevScrollY = _mScrollY; } } } }