Allow horizontal ListView. Rename height -> size

Summary:
Infinite scrolling in horizontal ListViews. Rather than just using height and Y offset to determine when to load more rows, it checks `props.horizontal` and switches between width/height and offset X/Y accordingly.

This changed required some renaming. However, the only change external to `ListView.js` is exporting `contentSize` instead of `contentHeight` from the `getMetrics()` function. (This is not part of the API, but is used "for perf investigations or analytics" and isn't reference in the repo).

I believe this change works as expected (and the xcode tests pass) though it's possible that there may more complexity in this issue that I have overlooked.
Closes https://github.com/facebook/react-native/pull/1786
Github Author: Mr Speaker <mrspeaker@gmail.com>
This commit is contained in:
Mr Speaker 2015-07-15 10:05:13 -07:00
parent 5006eca4a8
commit 09236ccbe7
1 changed files with 35 additions and 25 deletions

View File

@ -209,7 +209,7 @@ var ListView = React.createClass({
*/
getMetrics: function() {
return {
contentHeight: this.scrollProperties.contentHeight,
contentLength: this.scrollProperties.contentLength,
totalRows: this.props.dataSource.getRowCount(),
renderedRows: this.state.curRenderedRowsCount,
visibleRows: Object.keys(this._visibleRows).length,
@ -255,9 +255,9 @@ var ListView = React.createClass({
componentWillMount: function() {
// this data should never trigger a render pass, so don't put in state
this.scrollProperties = {
visibleHeight: null,
contentHeight: null,
offsetY: 0
visibleLength: null,
contentLength: null,
offset: 0
};
this._childFrames = [];
this._visibleRows = {};
@ -409,12 +409,12 @@ var ListView = React.createClass({
scrollComponent.getInnerViewNode(),
React.findNodeHandle(scrollComponent),
logError,
this._setScrollContentHeight
this._setScrollContentLength
);
RCTUIManager.measureLayoutRelativeToParent(
React.findNodeHandle(scrollComponent),
logError,
this._setScrollVisibleHeight
this._setScrollVisibleLength
);
// RCTScrollViewManager.calculateChildFrames is not available on
@ -426,12 +426,14 @@ var ListView = React.createClass({
);
},
_setScrollContentHeight: function(left, top, width, height) {
this.scrollProperties.contentHeight = height;
_setScrollContentLength: function(left, top, width, height) {
this.scrollProperties.contentLength = !this.props.horizontal ?
height : width;
},
_setScrollVisibleHeight: function(left, top, width, height) {
this.scrollProperties.visibleHeight = height;
_setScrollVisibleLength: function(left, top, width, height) {
this.scrollProperties.visibleLength = !this.props.horizontal ?
height : width;
this._updateVisibleRows();
this._renderMoreRowsIfNeeded();
},
@ -441,8 +443,8 @@ var ListView = React.createClass({
},
_renderMoreRowsIfNeeded: function() {
if (this.scrollProperties.contentHeight === null ||
this.scrollProperties.visibleHeight === null ||
if (this.scrollProperties.contentLength === null ||
this.scrollProperties.visibleLength === null ||
this.state.curRenderedRowsCount === this.props.dataSource.getRowCount()) {
return;
}
@ -472,9 +474,9 @@ var ListView = React.createClass({
},
_getDistanceFromEnd: function(scrollProperties) {
return scrollProperties.contentHeight -
scrollProperties.visibleHeight -
scrollProperties.offsetY;
return scrollProperties.contentLength -
scrollProperties.visibleLength -
scrollProperties.offset;
},
_updateVisibleRows: function(updatedFrames) {
@ -486,9 +488,10 @@ var ListView = React.createClass({
this._childFrames[newFrame.index] = merge(newFrame);
});
}
var isVertical = !this.props.horizontal;
var dataSource = this.props.dataSource;
var visibleTop = this.scrollProperties.offsetY;
var visibleBottom = visibleTop + this.scrollProperties.visibleHeight;
var visibleMin = this.scrollProperties.offset;
var visibleMax = visibleMin + this.scrollProperties.visibleLength;
var allRowIDs = dataSource.rowIdentities;
var header = this.props.renderHeader && this.props.renderHeader();
@ -516,9 +519,9 @@ var ListView = React.createClass({
break;
}
var rowVisible = visibleSection[rowID];
var top = frame.y;
var bottom = top + frame.height;
if (top > visibleBottom || bottom < visibleTop) {
var min = isVertical ? frame.y : frame.x;
var max = min + (isVertical ? frame.height : frame.width);
if (min > visibleMax || max < visibleMin) {
if (rowVisible) {
visibilityChanged = true;
delete visibleSection[rowID];
@ -546,16 +549,23 @@ var ListView = React.createClass({
},
_onScroll: function(e) {
this.scrollProperties.visibleHeight = e.nativeEvent.layoutMeasurement.height;
this.scrollProperties.contentHeight = e.nativeEvent.contentSize.height;
this.scrollProperties.offsetY = e.nativeEvent.contentOffset.y;
var isVertical = !this.props.horizontal;
this.scrollProperties.visibleLength = e.nativeEvent.layoutMeasurement[
isVertical ? 'height' : 'width'
];
this.scrollProperties.contentLength = e.nativeEvent.contentSize[
isVertical ? 'height' : 'width'
];
this.scrollProperties.offset = e.nativeEvent.contentOffset[
isVertical ? 'y' : 'x'
];
this._updateVisibleRows(e.nativeEvent.updatedChildFrames);
var nearEnd = this._getDistanceFromEnd(this.scrollProperties) < this.props.onEndReachedThreshold;
if (nearEnd &&
this.props.onEndReached &&
this.scrollProperties.contentHeight !== this._sentEndForContentHeight &&
this.scrollProperties.contentLength !== this._sentEndForContentLength &&
this.state.curRenderedRowsCount === this.props.dataSource.getRowCount()) {
this._sentEndForContentHeight = this.scrollProperties.contentHeight;
this._sentEndForContentLength = this.scrollProperties.contentLength;
this.props.onEndReached(e);
} else {
this._renderMoreRowsIfNeeded();