💥🔥Breaking Changes in v1.0.0:🔥💥
SwipeListView
now supports FlatList
! (and SectionList
)
Please see the section Migrating To FlatList for all details.
Migrating to SectionList
is very similar. Please see example.js
for a full usage example.
You can continue to use the (deprecated) ListView
component, however there are some BREAKING CHANGES that are explained in that section as well
<SwipeListView>
is a ListView with rows that swipe open and closed. Handles default native behavior such as closing rows when ListView is scrolled or when other rows are opened.
Also includes <SwipeRow>
if you want to use a swipeable row outside of the <SwipeListView>
Try it out! https://snack.expo.io/@jemise111/react-native-swipe-list-view
npm install --save react-native-swipe-list-view
The application under ./SwipeListExample will produce the above example. To run execute the following:
git clone https://github.com/jemise111/react-native-swipe-list-view.git
cd react-native-swipe-list-view
cd SwipeListExample
yarn
react-native run-ios | react-native run-android
import { SwipeListView } from 'react-native-swipe-list-view';
render() {
return (
<SwipeListView
useFlatList
data={this.state.listViewData}
renderItem={ (data, rowMap) => (
<View style={styles.rowFront}>
<Text>I am {data.item} in a SwipeListView</Text>
</View>
)}
renderHiddenItem={ (data, rowMap) => (
<View style={styles.rowBack}>
<Text>Left</Text>
<Text>Right</Text>
</View>
)}
leftOpenValue={75}
rightOpenValue={-75}
/>
)
}
See example.js
for full usage guide (including using <SwipeRow>
by itself)
If your row is touchable (TouchableOpacity, TouchableHighlight, etc.) with an onPress
function make sure renderItem
returns the Touchable as the topmost element.
GOOD:
renderItem={ data => (
<TouchableHighlight onPress={this.doSomething.bind(this)}>
<View>
<Text>I am {data.item} in a SwipeListView</Text>
</View>
</TouchableHighlight>
)}
BAD:
renderItem={ data => (
<View>
<TouchableHighlight onPress={this.doSomething.bind(this)}>
<Text>I am {data.item} in a SwipeListView</Text>
</TouchableHighlight>
</View>
)}
If your row or hidden row renders a touchable child and you'd like that touchable to close the row note that the renderItem
and renderHiddenItem
functions are passed rowData
, rowMap
. The rowMap
is an object that looks like:
{
row_key_1: ref_to_row_1,
row_key_2: ref_to_row_2
}
Where each row_key
is the same key used by the FlatList
taken either from the key
property on your data objects or using the keyExtractor
prop.
Each row's ref has a public method called closeRow
that will swipe the row closed. So you can do something like:
<SwipeListView
renderHiddenItem={ (rowData, rowMap) => {
<TouchableOpacity onPress={ _ => rowMap[rowData.item.key].closeRow() }>
<Text>I close the row</Text>
</TouchableOpacity>
}}
/>
If you are using the standalone <SwipeRow>
you can just keep a ref to the component and call closeRow()
on that ref.
If you need rows to behave independently you can return a <SwipeRow>
in the renderItem
function. Make sure you import the <SwipeRow>
in addition to the <SwipeListView>
. See the example below and the docs under API for how to implement a custom <SwipeRow>
. There is also a full example in example.js
.
The following values can be dynamic by passing them as props on the <SwipeRow>
:
leftOpenValue
rightOpenValue
stopLeftSwipe
stopRightSwipe
closeOnRowPress
disableLeftSwipe
disableRightSwipe
recalculateHiddenLayout
directionalDistanceChangeThreshold
import { SwipeListView, SwipeRow } from 'react-native-swipe-list-view';
<SwipeListView
dataSource={dataSource.cloneWithRows(data)}
renderItem={ (rowData, rowMap) => (
<SwipeRow
disableRightSwipe={parseInt(rowId) % 2 !== 0}
disableLeftSwipe={parseInt(rowId) % 2 === 0}
leftOpenValue={20 + parseInt(rowId) * 5}
rightOpenValue={-150}
>
<View style={styles.rowBack}>
<Text>Left Hidden</Text>
<Text>Right Hidden</Text>
</View>
<View style={styles.rowFront}>
<Text>Row front | {data.item.key}</Text>
</View>
</SwipeRow>
)}
/>
You can also customize your individual rows by passing in your row's data
next props:
leftOpenValue
rightOpenValue
closeOnRowPress
disableLeftSwipe
disableRightSwipe
stopLeftSwipe
stopRightSwipe
Example:
const dataSource = [
{
name: 'Andy',
age: 12,
disableRightSwipe: true,
},
{
name: 'Betty',
age: 11,
leftOpenValue: 150,
},
{
name: 'Carl',
age: 11,
},
];
In most ways migrating your SwipeListView
is no different than migrating your typical RN ListView
(renderRow
-> renderItem
, renderHiddenRow
-> renderHiddenItem
). The biggest difference is the identifier used to keep track of row ref's. Previously this was done using a unique hash for each row that looked like ${secId}${rowId}
. Now, since FlatList requires the use of a unique key
for each piece of data, the SwipeListView
uses this unique key to keep track of row refs in place of the unique hash.
The biggest breaking change you will find is the signature of certain callback functions used to pass the secId
and rowId
as two separate arguments, whereas now they will pass one argument, the row's unique key.
e.g.
onRowOpen(secId, rowId, rowMap) {
// Grab reference to this row
const rowRef = rowMap[`${secId}${rowId}`];
// Do something with the row
rowRef.closeRow();
}
would now look like:
onRowOpen(rowKey, rowMap, toValue) {
// Grab reference to this row
const rowRef = rowMap[rowKey];
// Do something with the row
rowRef.closeRow();
}
The other breaking change introduced is how to do a slideout preview. If you'd like to do a slide out preview for one of the rows simply use the new prop previewRowKey
and pass the key corrseponding with that row.
Here is a typical migration example:
BEFORE:
<SwipeListView
dataSource={this.ds.cloneWithRows(this.state.listViewData)}
renderRow={ (data, secId, rowId, rowMap) => (
<View>
<Text>I am {data} in a SwipeListView</Text>
</View>
)}
renderHiddenRow={ (data, secId, rowId, rowMap) => (
<View style={styles.rowBack}>
<TouchableOpacity onPress={ _ => rowMap[`${secId}${rowId}`].closeRow() }>
<Text>Close</Text>
</TouchableOpacity>
</View>
)}
leftOpenValue={75}
rightOpenValue={-150}
onRowOpen={(secId, rowId, rowMap) => {
setTimeout(() => {
rowMap[`${secId}${rowId}`].closeRow()
}, 2000)
}}
previewFirstRow={true}
/>
AFTER (Using FlatList):
<SwipeListView
useFlatList={true}
data={this.state.flatListData}
renderItem={ (rowData, rowMap) => (
<View>
<Text>I am {rowData.item.text} in a SwipeListView</Text>
</View>
)}
renderHiddenItem={ (rowData, rowMap) => (
<View style={styles.rowBack}>
<TouchableOpacity onPress={ _ => rowMap[rowData.item.key].closeRow() }>
<Text>Close</Text>
</TouchableOpacity>
</View>
)}
leftOpenValue={75}
rightOpenValue={-150}
onRowOpen={(rowKey, rowMap) => {
setTimeout(() => {
rowMap[rowKey].closeRow()
}, 2000)
}}
previewRowKey={this.state.flatListData[0].key}
/>
ListView that renders SwipeRows.
Render list using React Native's FlatList
type: bool
defaultValue: false
Render list using React Native's SectionList
type: bool
defaultValue: false
Should open rows be closed when a row is pressed
type: bool
defaultValue: true
Should open rows be closed when the listView begins scrolling
type: bool
defaultValue: true
Should open rows be closed when a row begins to swipe open
type: bool
defaultValue: false
Change the sensitivity of the row
type: number
defaultValue: 2
TranslateX value for opening the row to the left (positive number)
type: number
defaultValue: 0
TranslateX value for stop the row to the left (positive number)
This number is the stop value corresponding to the leftOpenValue
(while the row is swiping in the right direction)
type: number
TranslateX value for stop the row to the right (negative number)
This number is the stop value corresponding to the rightOpenValue
(while the row is swiping in the left direction)
type: number
renderHiddenItem
How to render a hidden row in a FlatList (renders behind the row). Should return a valid React Element.
This is required unless renderItem
returns a <SwipeRow>
(see Per Row Behavior).
type: func
params: (rowData, rowMap)
How to render a row in a FlatList. Should return a valid React Element.
type: func
params: (rowData, rowMap)
renderHiddenRow
[DEPRECATED]
How to render a hidden row (renders behind the row). Should return a valid React Element.
This is required unless renderRow
returns a <SwipeRow>
(see Per Row Behavior).
type: func
params: (rowData, secId, rowId, rowMap)
How to render a row. Should return a valid React Element.
type: func
params: (rowData, secId, rowId, rowMap)
TranslateX value for opening the row to the right (negative number)
type: number
defaultValue: 0
What % of the left/right openValue does the user need to swipe past to trigger the row opening.
type: number
defaultValue: 50
Describes how much the ending velocity of the gesture affects whether the swipe will result in the item being closed or open. A velocity factor of 0 (the default) means that the velocity will have no bearing on whether the swipe settles on a closed or open position and it'll just take into consideration the swipeToOpenPercent. Ideal values for this prop tend to be between 5 and 15.
type: number
defaultValue: 0
Disable ability to swipe the row left
type: bool
defaultValue: false
Disable ability to swipe the row right
type: bool
defaultValue: false
recalculateHiddenLayout
Enable hidden row onLayout calculations to run always.
By default, hidden row size calculations are only done on the first onLayout event
for performance reasons.
Passing true
here will cause calculations to run on every onLayout event.
You may want to do this if your rows' sizes can change.
One case is a SwipeListView with rows of different heights and an options to delete rows.
type: bool
defaultValue: false
Called when a swipe row is animating swipe
type: func
params: (rowKey)
Called when a swipe row is animating closed
type: func
params: (rowKey, rowMap)
Called when a swipe row has animated closed
type: func
params: (rowKey, rowMap)
Called when a swipe row is animating open.
This has a param of toValue
which is the new X value the row (after it has opened). This can be used to calculate which direction the row has been swiped open.
type: func
params: (rowKey, rowMap, toValue)
Called when a swipe row has animated open
type: func
params: (rowKey, rowMap, toValue)
Called when scrolling has been enabled/disabled
type: func
params: (isEnabled)
Styles for the parent wrapper View of the SwipeRow
type: object
Called when the ListView ref is set and passes a ref to the ListView
e.g. listViewRef={ ref => this._swipeListViewRef = ref }
type: func
params: (ref)
Should the row with this key do a slide out preview to show that the list is swipeable
type: string
Should the first SwipeRow do a slide out preview to show that the list is swipeable
type: bool
defaultValue: false
Should the specified rowId do a slide out preview to show that the list is swipeable
- Note: This ID will be passed to this function to get the correct row index
- https://facebook.github.io/react-native/docs/listviewdatasource.html#getrowidforflatindex
type: number
Duration of the slide out preview animation
type: number
TranslateX value for the slide out preview animation Default: 0.5 * props.rightOpenValue
type: number
Add some delay before opening the preview row. Can be Usefull when you have enter animation.
type: number
Friction for the open / close animation
type: number
Tension for the open / close animation
type: number
Row that is generally used in a SwipeListView. If you are rendering a SwipeRow explicitly you must pass the SwipeRow exactly two children. The first will be rendered behind the second. e.g.
<SwipeRow>
<View style={hiddenRowStyle} />
<View style={visibleRowStyle} />
</SwipeRow>
Should the row be closed when it is tapped
type: bool
defaultValue: true
Change the sensitivity of the row
type: number
defaultValue: 2
Friction for the open / close animation
type: number
TranslateX value for opening the row to the left (positive number)
type: number
defaultValue: 0
TranslateX value for stop the row to the left (positive number)
This number is the stop value corresponding to the leftOpenValue
(while the row is swiping in the right direction)
type: number
TranslateX value for stop the row to the right (negative number)
This number is the stop value corresponding to the rightOpenValue
(while the row is swiping in the left direction)
type: number
Called when a swipe row is pressed.
type: func
params: ()
Called when a swipe row is animating open. Used by the SwipeListView to keep references to open rows.
type: func
params: (toValue)
Called when a swipe row is animating closed
type: func
params: ()
TranslateX value for opening the row to the right (negative number)
type: number
defaultValue: 0
What % of the left/right openValue does the user need to swipe past to trigger the row opening.
type: number
defaultValue: 50
Used by the SwipeListView to close rows on scroll events. You shouldn't need to use this prop explicitly.
type: func
Tension for the open / close animation
type: number
Disable ability to swipe the row left
type: bool
defaultValue: false
Disable ability to swipe the row right
type: bool
defaultValue: false
recalculateHiddenLayout
Enable hidden row onLayout calculations to run always
type: bool
defaultValue: false
Styles for the parent wrapper View of the SwipeRow
type: object
Should the row do a slide out preview to show that it is swipeable
type: bool
defaultValue: false
Duration of the slide out preview animation
type: number
defaultValue: 300
TranslateX value for the slide out preview animation Default: 0.5 * props.rightOpenValue
type: number
RN Core added a SwipeList component as of v0.27.0
It is actively being worked on and has no documentation yet. So I will continue to maintain this component until a future date.
MIT