Skip to content

Commit

Permalink
Add renderSeparator support to ListView
Browse files Browse the repository at this point in the history
  • Loading branch information
Changgeng Li authored and tadeuzagallo committed May 28, 2015
1 parent e2b5661 commit 947ee2a
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 7 deletions.
6 changes: 4 additions & 2 deletions Examples/Movies/MovieCell.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ var MovieCell = React.createClass({
var criticsScore = this.props.movie.ratings.critics_score;
return (
<View>
<TouchableHighlight onPress={this.props.onSelect}>
<TouchableHighlight
onPress={this.props.onSelect}
onShowUnderlay={this.props.onHighlight}
onHideUnderlay={this.props.onUnhighlight}>
<View style={styles.row}>
<Image
source={getImageSource(this.props.movie, 'det')}
Expand All @@ -54,7 +57,6 @@ var MovieCell = React.createClass({
</View>
</View>
</TouchableHighlight>
<View style={styles.cellBorder} />
</View>
);
}
Expand Down
30 changes: 30 additions & 0 deletions Examples/Movies/Movies.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
140D9B661AC36C42004F25EE /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14312D241AC3654D00CDC950 /* libRCTLinking.a */; };
14A2D4421AC3E43800CC738A /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14A2D4411AC3E41A00CC738A /* libReact.a */; };
58C5726B1AA6239E00CDF9C8 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C5725B1AA6236500CDF9C8 /* libRCTText.a */; };
67C95F201B0E64A30040BCE2 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67C95F1E1B0E647A0040BCE2 /* libRCTWebSocket.a */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -54,6 +55,13 @@
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
remoteInfo = RCTText;
};
67C95F1D1B0E647A0040BCE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 67C95F151B0E647A0040BCE2 /* RCTWebSocket.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
remoteInfo = RCTWebSocket;
};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
Expand All @@ -69,13 +77,15 @@
14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
14A2D43C1AC3E41A00CC738A /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../../React/React.xcodeproj; sourceTree = "<group>"; };
587650F61A9EB120008B8F17 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = SOURCE_ROOT; };
67C95F151B0E647A0040BCE2 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../../Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
67C95F201B0E64A30040BCE2 /* libRCTWebSocket.a in Frameworks */,
14A2D4421AC3E43800CC738A /* libReact.a in Frameworks */,
140D9B661AC36C42004F25EE /* libRCTLinking.a in Frameworks */,
1341801E1AA91750003F314A /* libRCTNetwork.a in Frameworks */,
Expand Down Expand Up @@ -135,6 +145,7 @@
58C571FC1AA6124500CDF9C8 /* Libraries */ = {
isa = PBXGroup;
children = (
67C95F151B0E647A0040BCE2 /* RCTWebSocket.xcodeproj */,
14A2D43C1AC3E41A00CC738A /* React.xcodeproj */,
14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */,
134180151AA91740003F314A /* RCTNetwork.xcodeproj */,
Expand All @@ -152,6 +163,14 @@
name = Products;
sourceTree = "<group>";
};
67C95F161B0E647A0040BCE2 /* Products */ = {
isa = PBXGroup;
children = (
67C95F1E1B0E647A0040BCE2 /* libRCTWebSocket.a */,
);
name = Products;
sourceTree = "<group>";
};
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -228,6 +247,10 @@
ProductGroup = 58C572571AA6236500CDF9C8 /* Products */;
ProjectRef = 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */;
},
{
ProductGroup = 67C95F161B0E647A0040BCE2 /* Products */;
ProjectRef = 67C95F151B0E647A0040BCE2 /* RCTWebSocket.xcodeproj */;
},
{
ProductGroup = 14A2D43D1AC3E41A00CC738A /* Products */;
ProjectRef = 14A2D43C1AC3E41A00CC738A /* React.xcodeproj */;
Expand Down Expand Up @@ -276,6 +299,13 @@
remoteRef = 58C5725A1AA6236500CDF9C8 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
67C95F1E1B0E647A0040BCE2 /* libRCTWebSocket.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTWebSocket.a;
remoteRef = 67C95F1D1B0E647A0040BCE2 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */

/* Begin PBXResourcesBuildPhase section */
Expand Down
32 changes: 31 additions & 1 deletion Examples/Movies/SearchScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,31 @@ var SearchScreen = React.createClass({
return <ActivityIndicatorIOS style={styles.scrollSpinner} />;
},

renderRow: function(movie: Object) {
renderSeparator: function(
sectionID: number | string,
rowID: number | string,
adjacentRowHighlighted: boolean
) {
var style = styles.rowSeparator;
if (adjacentRowHighlighted) {
style = [style, styles.rowSeparatorHide];
}
return (
<View key={"SEP_" + sectionID + "_" + rowID} style={style}/>
);
},

renderRow: function(
movie: Object,
sectionID: number | string,
rowID: number | string,
highlightRowFunc: (sectionID: ?number | string, rowID: ?number | string) => void,
) {
return (
<MovieCell
onSelect={() => this.selectMovie(movie)}
onHighlight={() => highlightRowFunc(sectionID, rowID)}
onUnhighlight={() => highlightRowFunc(null, null)}
movie={movie}
/>
);
Expand All @@ -254,6 +275,7 @@ var SearchScreen = React.createClass({
/> :
<ListView
ref="listview"
renderSeparator={this.renderSeparator}
dataSource={this.state.dataSource}
renderFooter={this.renderFooter}
renderRow={this.renderRow}
Expand Down Expand Up @@ -352,6 +374,14 @@ var styles = StyleSheet.create({
scrollSpinner: {
marginVertical: 20,
},
rowSeparator: {
backgroundColor: 'rgba(0, 0, 0, 0.1)',
height: 1,
marginLeft: 4,
},
rowSeparatorHide: {
opacity: 0.0,
},
});

module.exports = SearchScreen;
10 changes: 10 additions & 0 deletions Libraries/Components/Touchable/TouchableHighlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ var TouchableHighlight = React.createClass({
*/
underlayColor: React.PropTypes.string,
style: View.propTypes.style,
/**
* Called immediately after the underlay is shown
*/
onShowUnderlay: React.PropTypes.func,
/**
* Called immediately after the underlay is hidden
*/
onHideUnderlay: React.PropTypes.func,
},

mixins: [NativeMethodsMixin, TimerMixin, Touchable.Mixin],
Expand Down Expand Up @@ -159,6 +167,7 @@ var TouchableHighlight = React.createClass({
_showUnderlay: function() {
this.refs[UNDERLAY_REF].setNativeProps(this.state.activeUnderlayProps);
this.refs[CHILD_REF].setNativeProps(this.state.activeProps);
this.props.onShowUnderlay && this.props.onShowUnderlay();
},

_hideUnderlay: function() {
Expand All @@ -170,6 +179,7 @@ var TouchableHighlight = React.createClass({
...INACTIVE_UNDERLAY_PROPS,
style: this.state.underlayStyle,
});
this.props.onHideUnderlay && this.props.onHideUnderlay();
}
},

Expand Down
41 changes: 37 additions & 4 deletions Libraries/CustomComponents/ListView/ListView.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,30 @@ var ListView = React.createClass({
* You must provide a renderRow function. If you omit any of the other render
* functions, ListView will simply skip rendering them.
*
* - renderRow(rowData, sectionID, rowID);
* - renderRow(rowData, sectionID, rowID, highlightRow);
* - renderSectionHeader(sectionData, sectionID);
*/
propTypes: {
...ScrollView.propTypes,

dataSource: PropTypes.instanceOf(ListViewDataSource).isRequired,
/**
* (rowData, sectionID, rowID) => renderable
* (sectionID, rowID, adjacentRowHighlighted) => renderable
* If provided, a renderable component to be rendered as the separator
* below each row but not the last row if there is a section header below.
* Take a sectionID and rowID of the row above and whether its adjacent row
* is highlighted.
*/
renderSeparator: PropTypes.func,
/**
* (rowData, sectionID, rowID, highlightRow) => renderable
* Takes a data entry from the data source and its ids and should return
* a renderable component to be rendered as the row. By default the data
* is exactly what was put into the data source, but it's also possible to
* provide custom extractors.
* provide custom extractors. ListView can be notified when a row is
* being highlighted by calling highlightRow function. The separators above and
* below will be hidden when a row is highlighted. The highlighted state of
* a row can be reset by calling highlightRow(null).
*/
renderRow: PropTypes.func.isRequired,
/**
Expand Down Expand Up @@ -227,6 +238,7 @@ var ListView = React.createClass({
return {
curRenderedRowsCount: this.props.initialListSize,
prevRenderedRowsCount: 0,
highlightedRow: {},
};
},

Expand Down Expand Up @@ -256,6 +268,10 @@ var ListView = React.createClass({
}
},

onRowHighlighted: function(sectionID, rowID) {
this.setState({highlightedRow: {sectionID, rowID}});
},

render: function() {
var bodyComponents = [];

Expand Down Expand Up @@ -305,11 +321,28 @@ var ListView = React.createClass({
null,
dataSource.getRowData(sectionIdx, rowIdx),
sectionID,
rowID
rowID,
this.onRowHighlighted
)}
/>;
bodyComponents.push(row);
totalIndex++;

if (this.props.renderSeparator &&
(rowIdx !== rowIDs.length - 1 || sectionIdx === allRowIDs.length -1)) {
var adjacentRowHighlighted =
this.state.highlightedRow.sectionID === sectionID && (
this.state.highlightedRow.rowID === rowID ||
this.state.highlightedRow.rowID === rowIDs[rowIdx + 1]
);
var separator = this.props.renderSeparator(
sectionID,
rowID,
adjacentRowHighlighted
);
bodyComponents.push(separator);
totalIndex++;
}
if (++rowCount === this.state.curRenderedRowsCount) {
break;
}
Expand Down

0 comments on commit 947ee2a

Please sign in to comment.