Add a prop to toggle ListView sticky section headers
Summary: Hello, This PR adds a property to the `ListView` to enable and disable to sticky sections headers behaviour. Current this is enabled by default and there is no way to disable it. It has been previously discussed in #1974 where there was a suggestion to add the `ListView` inside `ScrollView`. This is bad for performance, but some people were using that as a workaround. satya164 suggested someone submitting a PR, which is why I'm here 😉 I have tested the property manually by adding `stickySectionHeaders={false}` to the `<ListView> Paging` example in `UIExplorer`. I have also tested that the current behaviour still stands, so this is a non-breaking change. I have also checked that the website displays the new documentation. I couldn't see anywhere to add automated tests to this, but if there is feel free to point it out and I'll update this PR. I tried running `npm run lint` to check the code style, but it spat out loads and loads of errors. I presume I have something set up incorrectly. Feel Closes https://github.com/facebook/react-native/pull/11700 Differential Revision: D4380916 fbshipit-source-id: 7782043afc9f0108c81f97952fed60b153479cac
This commit is contained in:
parent
5fdd6b33fa
commit
55427566b6
|
@ -56,7 +56,7 @@ var DEFAULT_SCROLL_CALLBACK_THROTTLE = 50;
|
|||
|
||||
/**
|
||||
* ListView - A core component designed for efficient display of vertically
|
||||
* scrolling lists of changing data. The minimal API is to create a
|
||||
* scrolling lists of changing data. The minimal API is to create a
|
||||
* [`ListView.DataSource`](docs/listviewdatasource.html), populate it with a simple
|
||||
* array of data blobs, and instantiate a `ListView` component with that data
|
||||
* source and a `renderRow` callback which takes a blob from the data array and
|
||||
|
@ -100,7 +100,7 @@ var DEFAULT_SCROLL_CALLBACK_THROTTLE = 50;
|
|||
* source data has changed - see ListViewDataSource for more details.
|
||||
*
|
||||
* * Rate-limited row rendering - By default, only one row is rendered per
|
||||
* event-loop (customizable with the `pageSize` prop). This breaks up the
|
||||
* event-loop (customizable with the `pageSize` prop). This breaks up the
|
||||
* work into smaller chunks to reduce the chance of dropping frames while
|
||||
* rendering rows.
|
||||
*/
|
||||
|
@ -145,7 +145,7 @@ var ListView = React.createClass({
|
|||
* (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
|
||||
* 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. ListView can be notified when a row is
|
||||
* being highlighted by calling `highlightRow(sectionID, rowID)`. This
|
||||
|
@ -155,14 +155,14 @@ var ListView = React.createClass({
|
|||
*/
|
||||
renderRow: PropTypes.func.isRequired,
|
||||
/**
|
||||
* How many rows to render on initial component mount. Use this to make
|
||||
* How many rows to render on initial component mount. Use this to make
|
||||
* it so that the first screen worth of data appears at one time instead of
|
||||
* over the course of multiple frames.
|
||||
*/
|
||||
initialListSize: PropTypes.number.isRequired,
|
||||
/**
|
||||
* Called when all rows have been rendered and the list has been scrolled
|
||||
* to within onEndReachedThreshold of the bottom. The native scroll
|
||||
* to within onEndReachedThreshold of the bottom. The native scroll
|
||||
* event is provided.
|
||||
*/
|
||||
onEndReached: PropTypes.func,
|
||||
|
@ -182,8 +182,8 @@ var ListView = React.createClass({
|
|||
* () => renderable
|
||||
*
|
||||
* The header and footer are always rendered (if these props are provided)
|
||||
* on every render pass. If they are expensive to re-render, wrap them
|
||||
* in StaticContainer or other mechanism as appropriate. Footer is always
|
||||
* on every render pass. If they are expensive to re-render, wrap them
|
||||
* in StaticContainer or other mechanism as appropriate. Footer is always
|
||||
* at the bottom of the list, and header at the top, on every render pass.
|
||||
*/
|
||||
renderFooter: PropTypes.func,
|
||||
|
@ -191,13 +191,7 @@ var ListView = React.createClass({
|
|||
/**
|
||||
* (sectionData, sectionID) => renderable
|
||||
*
|
||||
* If provided, a sticky header is rendered for this section. The sticky
|
||||
* behavior means that it will scroll with the content at the top of the
|
||||
* section until it reaches the top of the screen, at which point it will
|
||||
* stick to the top until it is pushed off the screen by the next section
|
||||
* header.
|
||||
*
|
||||
* NOTE: On Android, the header is not sticky.
|
||||
* If provided, a header is rendered for this section.
|
||||
*/
|
||||
renderSectionHeader: PropTypes.func,
|
||||
/**
|
||||
|
@ -215,7 +209,7 @@ var ListView = React.createClass({
|
|||
/**
|
||||
* (visibleRows, changedRows) => void
|
||||
*
|
||||
* Called when the set of visible rows changes. `visibleRows` maps
|
||||
* Called when the set of visible rows changes. `visibleRows` maps
|
||||
* { sectionID: { rowID: true }} for all the visible rows, and
|
||||
* `changedRows` maps { sectionID: { rowID: true | false }} for the rows
|
||||
* that have changed their visibility, with true indicating visible, and
|
||||
|
@ -225,9 +219,17 @@ var ListView = React.createClass({
|
|||
/**
|
||||
* A performance optimization for improving scroll perf of
|
||||
* large lists, used in conjunction with overflow: 'hidden' on the row
|
||||
* containers. This is enabled by default.
|
||||
* containers. This is enabled by default.
|
||||
*/
|
||||
removeClippedSubviews: React.PropTypes.bool,
|
||||
/**
|
||||
* Makes the sections headers sticky. The sticky behavior means that it
|
||||
* will scroll with the content at the top of the section until it reaches
|
||||
* the top of the screen, at which point it will stick to the top until it
|
||||
* is pushed off the screen by the next section header.
|
||||
* @platform ios
|
||||
*/
|
||||
stickySectionHeadersEnabled: React.PropTypes.bool,
|
||||
/**
|
||||
* An array of child indices determining which children get docked to the
|
||||
* top of the screen when scrolling. For example, passing
|
||||
|
@ -304,6 +306,7 @@ var ListView = React.createClass({
|
|||
renderScrollComponent: props => <ScrollView {...props} />,
|
||||
scrollRenderAheadDistance: DEFAULT_SCROLL_RENDER_AHEAD,
|
||||
onEndReachedThreshold: DEFAULT_END_REACHED_THRESHOLD,
|
||||
stickySectionHeadersEnabled: true,
|
||||
stickyHeaderIndices: [],
|
||||
};
|
||||
},
|
||||
|
@ -374,7 +377,7 @@ var ListView = React.createClass({
|
|||
var dataSource = this.props.dataSource;
|
||||
var allRowIDs = dataSource.rowIdentities;
|
||||
var rowCount = 0;
|
||||
var sectionHeaderIndices = [];
|
||||
var stickySectionHeaderIndices = [];
|
||||
|
||||
var header = this.props.renderHeader && this.props.renderHeader();
|
||||
var footer = this.props.renderFooter && this.props.renderFooter();
|
||||
|
@ -413,7 +416,9 @@ var ListView = React.createClass({
|
|||
)}
|
||||
/>
|
||||
);
|
||||
sectionHeaderIndices.push(totalIndex++);
|
||||
if (this.props.stickySectionHeadersEnabled) {
|
||||
stickySectionHeaderIndices.push(totalIndex++);
|
||||
}
|
||||
}
|
||||
|
||||
for (var rowIdx = 0; rowIdx < rowIDs.length; rowIdx++) {
|
||||
|
@ -474,7 +479,7 @@ var ListView = React.createClass({
|
|||
}
|
||||
Object.assign(props, {
|
||||
onScroll: this._onScroll,
|
||||
stickyHeaderIndices: this.props.stickyHeaderIndices.concat(sectionHeaderIndices),
|
||||
stickyHeaderIndices: this.props.stickyHeaderIndices.concat(stickySectionHeaderIndices),
|
||||
|
||||
// Do not pass these events downstream to ScrollView since they will be
|
||||
// registered in ListView's own ScrollResponder.Mixin
|
||||
|
|
Loading…
Reference in New Issue