Close open rows on scroll

Summary: If a user scrolls the `SwipeableListView`, any open row(s) will close.

Reviewed By: furdei

Differential Revision: D3903787

fbshipit-source-id: efd9ae896ba50ad6e83e72d52bc1f5c0c35efd61
This commit is contained in:
Fred Liu 2016-09-22 09:48:49 -07:00 committed by Facebook Github Bot 1
parent 61eb3e8826
commit 5c13eaccbd
1 changed files with 45 additions and 29 deletions

View File

@ -30,6 +30,19 @@ const SwipeableRow = require('SwipeableRow');
const {PropTypes} = React;
type Props = {
bounceFirstRowOnMount: boolean,
dataSource: SwipeableListViewDataSource,
maxSwipeDistance: number,
renderRow: Function,
renderQuickActions: Function,
};
type State = {
dataSource: Object,
scrollEnabled: boolean,
};
/**
* A container component that renders multiple SwipeableRow's in a ListView
* implementation. This is designed to be a drop-in replacement for the
@ -49,20 +62,18 @@ const {PropTypes} = React;
* - More to come
*/
class SwipeableListView extends React.Component {
props: {
bounceFirstRowOnMount: boolean,
dataSource: SwipeableListViewDataSource,
maxSwipeDistance: number,
renderRow: Function,
renderQuickActions: Function,
};
props: Props;
state: State;
_listViewRef: ?ReactElement<any> = null;
_shouldBounceFirstRowOnMount: boolean = false;
static getNewDataSource(): Object {
return new SwipeableListViewDataSource({
getRowData: (data, sectionID, rowID) => data[sectionID][rowID],
getSectionHeaderData: (data, sectionID) => data[sectionID],
sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
rowHasChanged: (row1, row2) => row1 !== row2,
sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
});
}
@ -90,21 +101,18 @@ class SwipeableListView extends React.Component {
renderQuickActions: () => null,
};
state: Object = {
dataSource: this.props.dataSource,
};
constructor(props: Props, context: any): void {
super(props, context);
_listViewRef: ?ReactElement<any> = null;
_shouldBounceFirstRowOnMount = false;
componentWillMount(): void {
this._shouldBounceFirstRowOnMount = this.props.bounceFirstRowOnMount;
this.state = {
dataSource: this.props.dataSource,
scrollEnabled: true,
};
}
componentWillReceiveProps(nextProps: Object): void {
if (
this.state.dataSource.getDataSource() !== nextProps.dataSource.getDataSource()
) {
componentWillReceiveProps(nextProps: Props): void {
if (this.state.dataSource.getDataSource() !== nextProps.dataSource.getDataSource()) {
this.setState({
dataSource: nextProps.dataSource,
});
@ -119,34 +127,42 @@ class SwipeableListView extends React.Component {
this._listViewRef = ref;
}}
dataSource={this.state.dataSource.getDataSource()}
onScroll={this._onScroll}
renderRow={this._renderRow}
scrollEnabled={this.state.scrollEnabled}
/>
);
}
_onScroll = (): void => {
// Close any opens rows on ListView scroll
if (this.props.dataSource.getOpenRowID()) {
this.setState({
dataSource: this.state.dataSource.setOpenRowID(null),
});
}
}
/**
* This is a work-around to lock vertical `ListView` scrolling on iOS and
* mimic Android behaviour. Locking vertical scrolling when horizontal
* scrolling is active allows us to significantly improve framerates
* (from high 20s to almost consistently 60 fps)
*/
_setListViewScrollable = (value: boolean): void => {
if (this._listViewRef &&
typeof this._listViewRef.setNativeProps === 'function') {
_setListViewScrollable(value: boolean): void {
if (this._listViewRef && typeof this._listViewRef.setNativeProps === 'function') {
this._listViewRef.setNativeProps({
scrollEnabled: value,
});
}
};
}
// Passing through ListView's getScrollResponder() function
getScrollResponder = (): ?Object => {
if (this._listViewRef &&
typeof this._listViewRef.getScrollResponder === 'function') {
getScrollResponder(): ?Object {
if (this._listViewRef && typeof this._listViewRef.getScrollResponder === 'function') {
return this._listViewRef.getScrollResponder();
}
};
}
_renderRow = (rowData: Object, sectionID: string, rowID: string): ReactElement<any> => {
const slideoutView = this.props.renderQuickActions(rowData, sectionID, rowID);
@ -177,11 +193,11 @@ class SwipeableListView extends React.Component {
);
};
_onOpen = (rowID: string): void => {
_onOpen(rowID: string): void {
this.setState({
dataSource: this.state.dataSource.setOpenRowID(rowID),
});
};
}
}
module.exports = SwipeableListView;