react-native 之SwipeableFlatList 側滑單項解決方案
阿新 • • 發佈:2018-12-31
react-native 側滑元件SwipeableFlatList 單項側滑解決
SwipeableFlatList 元件是 rn 0.50 出的 提供android ios 側滑刪除
/**
* 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({
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,
},
//側滑選單的樣式
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>
//如有理解有誤 敬請諒解