diff --git a/iron-list.js b/iron-list.js index 3ecff251..eeb6b09a 100644 --- a/iron-list.js +++ b/iron-list.js @@ -803,9 +803,11 @@ Polymer({ Math.round(delta / this._physicalAverage) * this._itemsPerRow; this._virtualStart = this._virtualStart + idxAdjustment; this._physicalStart = this._physicalStart + idxAdjustment; - // Estimate new physical offset. - this._physicalTop = Math.floor(this._virtualStart / this._itemsPerRow) * - this._physicalAverage; + // Estimate new physical offset based on the virtual start (but never allow + // to be more than the current scrollTop) + this._physicalTop = Math.min( + Math.floor(this._virtualStart / this._itemsPerRow) * + this._physicalAverage, this._scrollPosition); this._update(); } else if (this._physicalCount > 0) { var reusables = this._getReusables(isScrollingDown); @@ -841,7 +843,8 @@ Polymer({ var physicalCount = this._physicalCount; var top = this._physicalTop + this._scrollOffset; var bottom = this._physicalBottom + this._scrollOffset; - var scrollTop = this._scrollTop; + // This may be called outside of a scrollHandler, so use last cached position + var scrollTop = this._scrollPosition; var scrollBottom = this._scrollBottom; if (fromTop) { @@ -1362,7 +1365,8 @@ Polymer({ // Note: the delta can be positive or negative. if (deltaHeight !== 0) { this._physicalTop = this._physicalTop - deltaHeight; - var scrollTop = this._scrollTop; + // This may be called outside of a scrollHandler, so use last cached position + var scrollTop = this._scrollPosition; // juking scroll position during interial scrolling on iOS is no bueno if (!IOS_TOUCH_SCROLLING && scrollTop > 0) { this._resetScrollPosition(scrollTop - deltaHeight); diff --git a/test/basic.html b/test/basic.html index 0b0cfdd5..849bebeb 100644 --- a/test/basic.html +++ b/test/basic.html @@ -32,10 +32,16 @@ + + + diff --git a/test/fixtures/odd-sized-list.js b/test/fixtures/odd-sized-list.js new file mode 100644 index 00000000..87add037 --- /dev/null +++ b/test/fixtures/odd-sized-list.js @@ -0,0 +1,58 @@ +/** +@license +Copyright (c) 3015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at +http://polymer.github.io/LICENSE The complete set of authors may be found at +http://polymer.github.io/AUTHORS The complete set of contributors may be found +at http://polymer.github.io/CONTRIBUTORS Code distributed by Google as part of +the polymer project is also subject to an additional IP rights grant found at +http://polymer.github.io/PATENTS +*/ +import '@polymer/polymer/polymer-legacy.js'; + +import '../../iron-list.js'; +import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js'; +import {html} from '@polymer/polymer/lib/utils/html-tag.js'; +Polymer({ + is: 'odd-sized-list', + _template: html` + + + + `, + properties: { + items: { + value: function() { + // Some hand-tuned sizes to ensure the physical average + // after scrolling back up is such to trigger the bug + const items = []; + while (items.length < 70) { + items.push(30); + } + while (items.length < 90) { + items.push(90); + } + while (items.length < 5000) { + items.push(30); + } + return items; + } + } + } +});