原文鏈接 https://blog.csdn.net/qq_22329521/article/details/81987595
react-native 側(cè)滑組件SwipeableFlatList 單項側(cè)滑解決
SwipeableFlatList 組件是 rn 0.50 出的 提供android ios 側(cè)滑刪除
效果如下

1535026425(1).png
//ui 網(wǎng)上copy代碼
ui 參考https://blog.csdn.net/yu_m_k/article/details/80580250 拷貝下來的
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, SwipeableFlatList, TouchableHighlight } from 'react-native';
const CITY_NAMES = ['北京', '上海', '廣州', '杭州', '蘇州'];
export default class App extends Component<Props> {
render() {
return (
<View style={styles.container}>
<SwipeableFlatList
//1數(shù)據(jù)的獲取和渲染
data={CITY_NAMES}
renderItem={(data) => <View style={styles.item}>
<Text style={styles.text}>{data.item}</Text>
</View>}
//2創(chuàng)建側(cè)滑菜單
renderQuickActions={() => this.getQuickActions()}//創(chuàng)建側(cè)滑菜單
maxSwipeDistance={80}//可展開(滑動)的距離
bounceFirstRowOnMount={false}//進(jìn)去的時候不展示側(cè)滑效果
/>
</View>
);
}
//側(cè)滑菜單渲染
getQuickActions = () => {
return <View style={styles.quickAContent}>
<TouchableHighlight
onPress={() => alert("確認(rèn)刪除?")}
>
<View style={styles.quick}>
<Text style={styles.delete}>刪除</Text>
</View>
</TouchableHighlight>
</View>
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
item: {
backgroundColor: '#aeffb1',
height: 100,
marginRight: 15,
marginLeft: 15,
marginBottom: 10,
alignItems: 'center',
justifyContent: 'center',
elevation: 5,//漂浮的效果
borderRadius: 5,//圓角
},
text: {
color: '#444444',
fontSize: 20,
},
//側(cè)滑菜單的樣式
quickAContent: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
marginRight: 15,
marginBottom: 10,
},
quick: {
backgroundColor: "#ff1d49",
flex: 1,
alignItems: 'flex-end',//水平靠右
justifyContent: 'center',//上下居中
width: 100,
borderRadius: 5,
elevation: 5,//漂浮的效果
},
delete: {
color: "#d8fffa",
marginRight: 30
}
});
bug點在于 該組件api 說明不提供關(guān)閉側(cè)滑功能 以及只支持單個側(cè)滑(及打開一個側(cè)滑關(guān)閉上面的側(cè)滑)
分析源碼
在node_modules/react-native/Libraies/Experimental/SwipeableRow/ 下面
在
SwipeableFlatList
看到 render 仍是FlatList 看到他里面renderItem
_renderItem = (info: Object): ?React.Element<any> => {
const slideoutView = this.props.renderQuickActions(info);
const key = this.props.keyExtractor(info.item, info.index);
//就有無側(cè)滑
// If renderQuickActions is unspecified or returns falsey, don't allow swipe
if (!slideoutView) {
return this.props.renderItem(info);
}
let shouldBounceOnMount = false;
if (this._shouldBounceFirstRowOnMount) {
this._shouldBounceFirstRowOnMount = false;
shouldBounceOnMount = true;
}
return (
<SwipeableRow
slideoutView={slideoutView}
//這里我們看到他實際上是每個打開關(guān)閉都是有的但是flatlist不刷新
isOpen={key === this.state.openRowKey}
maxSwipeDistance={this._getMaxSwipeDistance(info)}
onOpen={() => this._onOpen(key)}
onClose={() => this._onClose(key)}
shouldBounceOnMount={shouldBounceOnMount}
onSwipeEnd={this._setListViewScrollable}
onSwipeStart={this._setListViewNotScrollable}>
{this.props.renderItem(info)}
</SwipeableRow>
);
};
_onOpen(key: any): void {
this.setState({
openRowKey: key,
});
}
_onClose(key: any): void {
this.setState({
openRowKey: null,
});
}
在 SwipeableRow組件中
UNSAFE_componentWillReceiveProps(nextProps: Object): void {
/**
* We do not need an "animateOpen(noCallback)" because this animation is
* handled internally by this component.
*/
也是做了isOpen 更新會出處罰這關(guān)閉item
if (this.props.isOpen && !nextProps.isOpen) {
this._animateToClosedPosition();
}
},
看了什么實際上SwipeableFlatList 是做了只支持單項了操作但是為什么能開啟多個側(cè)滑那
原因在于flatlist 的data 是數(shù)組引用問題 data如果引用不變是不會觸發(fā)flatlist的刷新
這里就需要用到一個 flatlist extraData 的屬性
extraData
如果有除data以外的數(shù)據(jù)用在列表中(不論是用在renderItem還是頭部或者尾部組件中),請在此屬性中指定。同時此數(shù)據(jù)在修改時也需要先修改其引用地址(比如先復(fù)制到一個新的 Object 或者數(shù)組中),然后再修改其值,否則界面很可能不會刷新。
我們修改源碼
render(): React.Node {
return (
<FlatList
{...this.props}
ref={ref => {
this._flatListRef = ref;
}}
//就加入這行效果就可行了
extraData={{
...this.state,
...this.props.extraData
}}
onScroll={this._onScroll}
renderItem={this._renderItem}
/>
);
}
這里我們封裝一個新的SwipeableFlatList 來避免修改源碼的方式
import { SwipeableFlatList, FlatList } from 'react-native'
import React from 'react'
export default class fixSwipeadFlatList extends SwipeableFlatList {
render(): React.Node {
return (
<FlatList
{...this.props}
ref={ref => {
this._flatListRef = ref;
}}
extraData={this.state}
onScroll={this._onScroll}
renderItem={this._renderItem}
/>
);
}
}
還有 當(dāng)你單擊完手動關(guān)閉側(cè)滑 我們看到 SwipeableFlatList 是提供了 我們自己使用引用去手動調(diào)關(guān)閉方法
_onClose(key: any): void {
this.setState({
openRowKey: null,
});
手動關(guān)閉側(cè)滑
<SwipeableFlatList
//1數(shù)據(jù)的獲取和渲染
data={CITY_NAMES}
renderItem={(data) => <View style={styles.item}>
<Text style={styles.text}>{data.item}</Text>
</View>}
ref={ref => {
this._flatListRef = ref;
}}
//2創(chuàng)建側(cè)滑菜單
renderQuickActions={() => this.getQuickActions()}//創(chuàng)建側(cè)滑菜單
maxSwipeDistance={80}//可展開(滑動)的距離
bounceFirstRowOnMount={false}//進(jìn)去的時候不展示側(cè)滑效果
/>
<TouchableHighlight
onPress={() =>this._flatListRef._onClose()}
>
<View style={styles.quick}>
<Text style={styles.delete}>刪除</Text>
</View>
</TouchableHighlight>
//如有理解有誤 敬請諒解