react-native 侧滑组件SwipeableFlatList 单项侧滑解决
SwipeableFlatList 组件是 rn 0.50 出的 提供android ios 侧滑删除
效果如下
//ui 网上copy代码
ui 参考 拷贝下来的
/**
* 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数据的获取和渲染
data={CITY_NAMES}
renderItem={(data) => <View style={styles.item}>
<Text style={styles.text}>{data.item}</Text>
</View>}
//2创建侧滑菜单
renderQuickActions={() => this.getQuickActions()}//创建侧滑菜单
maxSwipeDistance={80}//可展开(滑动)的距离
bounceFirstRowOnMount={false}//进去的时候不展示侧滑效果
/>
</View>
);
}
//侧滑菜单渲染
getQuickActions = () => {
return <View style={styles.quickAContent}>
<TouchableHighlight
onPress={() => alert("确认删除?")}
>
<View style={styles.quick}>
<Text style={styles.delete}>删除</Text>
</View>
</TouchableHighlight>
</View>
};
}
const styles = StyleSheet.create({
: {
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,
},
//侧滑菜单的样式
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 说明不提供关闭侧滑功能 以及只支持单个侧滑(及打开一个侧滑关闭上面的侧滑)
分析源码
在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);
//就有无侧滑
// 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}
//这里我们看到他实际上是每个打开关闭都是有的但是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 更新会出处罚这关闭item
if (this.props.isOpen && !nextProps.isOpen) {
this._animateToClosedPosition();
}
},
看了什么实际上SwipeableFlatList 是做了只支持单项了操作但是为什么能开启多个侧滑那
原因在于flatlist 的data 是数组引用问题 data如果引用不变是不会触发flatlist的刷新
这里就需要用到一个 flatlist extraData 的属性
extraData
如果有除data以外的数据用在列表中(不论是用在renderItem还是头部或者尾部组件中),请在此属性中指定。同时此数据在修改时也需要先修改其引用地址(比如先复制到一个新的 Object 或者数组中),然后再修改其值,否则界面很可能不会刷新。
我们修改源码
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}
/>
);
}
}
还有 当你单击完手动关闭侧滑 我们看到 SwipeableFlatList 是提供了 我们自己使用引用去手动调关闭方法
_onClose(key: any): void {
this.setState({
openRowKey: null,
});
手动关闭侧滑
<SwipeableFlatList
//1数据的获取和渲染
data={CITY_NAMES}
renderItem={(data) => <View style={styles.item}>
<Text style={styles.text}>{data.item}</Text>
</View>}
ref={ref => {
this._flatListRef = ref;
}}
//2创建侧滑菜单
renderQuickActions={() => this.getQuickActions()}//创建侧滑菜单
maxSwipeDistance={80}//可展开(滑动)的距离
bounceFirstRowOnMount={false}//进去的时候不展示侧滑效果
/>
<TouchableHighlight
onPress={() =>this._flatListRef._onClose()}
>
<View style={styles.quick}>
<Text style={styles.delete}>删除</Text>
</View>
</TouchableHighlight>