如何在列表视图(react-native)上制作滑动功能?
How to make swipe function on listview (react-native)?
我有物品清单。我为此使用 ListView,我需要能够通过向左或向右滑动来删除任何行。
我可以从哪里开始?
如果您愿意,请关注this guide which uses React Native Swipeout。
否则,这是我的 SwipeList 和 SwipeListRow 组件。我部分使用我的库 Cairn 来设置样式,但如果您愿意的话,它应该可以很容易地转换成普通的 React 样式表:
SwipeList.js
import React from 'react';
import { Text, ListView } from 'react-native';
import styleContext from 'app/style';
const style = styleContext.extend({
listViewSection: {
paddingVertical: 10,
paddingLeft: 15,
backgroundColor: '$greyDefault'
},
'text.listViewSection': {
color: '$greyMid',
fontSize: 16,
marginLeft: 5
}
});
function SwipeList({ dataSource, renderRow }) {
function renderSectionHeader(sectionData, sectionId) {
return (
<View {...style('listViewSection')}>
<Text {...style('text.listViewSection')}>{sectionId.toUpperCase()}</Text>
</View>
);
}
if (!dataSource.rowIdentities.length) {
return (
<Text>No items found.</Text>
);
}
return (
<ListView
dataSource={dataSource}
automaticallyAdjustContentInsets={false}
directionalLockEnabled
keyboardShouldPersistTaps={false}
keyboardDismissMode={'on-drag'}
renderSectionHeader={renderSectionHeader}
renderRow={renderRow} />
);
}
SwipeList.propTypes = {
dataSource: React.PropTypes.shape({
rowIdentities: React.PropTypes.array.isRequired
}).isRequired,
renderRow: React.PropTypes.func.isRequired
};
export default SwipeList;
SwipeListRow.js
import React from 'react';
import {
View,
Text,
ScrollView,
Animated,
Dimensions
} from 'react-native';
import styleContext from 'app/style';
const { width } = Dimensions.get('window');
const style = styleContext.extend({
swipeMessage: {
position: 'absolute',
top: 0,
height: 75,
justifyContent: 'center',
alignItems: 'center'
},
itemContainer: {
width
}
});
const WHITE = 0;
const GREEN = 1;
const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);
class SwipeListRow extends React.Component {
constructor(props) {
super(props);
this.state = {
color: new Animated.Value(WHITE)
};
}
animateScroll = (e) => {
const threshold = width / 5;
let x = e.nativeEvent.contentOffset.x;
let swiped = null;
x = x * -1;
if (x > -50 && this.swiped !== WHITE) {
swiped = WHITE;
} else if (x < -50 && x > -threshold && this.swiped !== GREEN) {
swiped = GREEN;
}
if (swiped !== null) {
this.swiped = swiped;
Animated.timing(this.state.color, {
toValue: swiped,
duration: 200
}).start();
}
}
takeAction = () => {
if (this.swiped) {
Animated.timing(this.state.color, {
toValue: WHITE,
duration: 200
}).start();
this.props.onSwipe();
}
}
render() {
const { swipeEnabled, swipeMessage, children } = this.props;
const bgColor = this.state.color.interpolate({
inputRange: [
WHITE,
GREEN
],
outputRange: [
'rgb(255, 255, 255)',
'rgb(123, 204, 40)'
]
});
return (
<View>
<AnimatedScrollView
horizontal
directionalLockEnabled
automaticallyAdjustContentInsets={false}
onScroll={this.animateScroll}
scrollEventThrottle={16}
scrollEnabled={swipeEnabled}
onMomentumScrollBegin={this.takeAction}
style={[{ flex: 1 }, { backgroundColor: bgColor }]}>
<View>
<View {...style('itemContainer')}>
{children}
</View>
<View
{...style(
'swipeMessage',
[{ width: width / 5, right: -width / 5 - 20 }]
)}>
<Text {...style('text.bold text.white')}>{swipeMessage}</Text>
</View>
</View>
</AnimatedScrollView>
</View>
);
}
}
SwipeListRow.propTypes = {
children: React.PropTypes.node.isRequired,
onSwipe: React.PropTypes.func.isRequired,
swipeEnabled: React.PropTypes.bool.isRequired,
swipeMessage: React.PropTypes.string.isRequired
};
export default SwipeListRow;
有了这些组件,现在您所要做的就是像在 ListView component documentation.
中描述的那样将所需的数据源传递给普通列表视图
<SwipeList
dataSource={dataSource}
renderRow={(item) => (
<SwipeListRow
key={item.id}
swipeMessage={'Delete Item'}
onSwipe={() => deleteItem(item)}
swipeEnabled={true}>
<<< INSERT DISPLAY OF ROW HERE >>>
</SwipeListRow>
)} />
用这个
这真的很好用,你可以扩展到任何东西。
我有物品清单。我为此使用 ListView,我需要能够通过向左或向右滑动来删除任何行。
我可以从哪里开始?
如果您愿意,请关注this guide which uses React Native Swipeout。
否则,这是我的 SwipeList 和 SwipeListRow 组件。我部分使用我的库 Cairn 来设置样式,但如果您愿意的话,它应该可以很容易地转换成普通的 React 样式表:
SwipeList.js
import React from 'react';
import { Text, ListView } from 'react-native';
import styleContext from 'app/style';
const style = styleContext.extend({
listViewSection: {
paddingVertical: 10,
paddingLeft: 15,
backgroundColor: '$greyDefault'
},
'text.listViewSection': {
color: '$greyMid',
fontSize: 16,
marginLeft: 5
}
});
function SwipeList({ dataSource, renderRow }) {
function renderSectionHeader(sectionData, sectionId) {
return (
<View {...style('listViewSection')}>
<Text {...style('text.listViewSection')}>{sectionId.toUpperCase()}</Text>
</View>
);
}
if (!dataSource.rowIdentities.length) {
return (
<Text>No items found.</Text>
);
}
return (
<ListView
dataSource={dataSource}
automaticallyAdjustContentInsets={false}
directionalLockEnabled
keyboardShouldPersistTaps={false}
keyboardDismissMode={'on-drag'}
renderSectionHeader={renderSectionHeader}
renderRow={renderRow} />
);
}
SwipeList.propTypes = {
dataSource: React.PropTypes.shape({
rowIdentities: React.PropTypes.array.isRequired
}).isRequired,
renderRow: React.PropTypes.func.isRequired
};
export default SwipeList;
SwipeListRow.js
import React from 'react';
import {
View,
Text,
ScrollView,
Animated,
Dimensions
} from 'react-native';
import styleContext from 'app/style';
const { width } = Dimensions.get('window');
const style = styleContext.extend({
swipeMessage: {
position: 'absolute',
top: 0,
height: 75,
justifyContent: 'center',
alignItems: 'center'
},
itemContainer: {
width
}
});
const WHITE = 0;
const GREEN = 1;
const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);
class SwipeListRow extends React.Component {
constructor(props) {
super(props);
this.state = {
color: new Animated.Value(WHITE)
};
}
animateScroll = (e) => {
const threshold = width / 5;
let x = e.nativeEvent.contentOffset.x;
let swiped = null;
x = x * -1;
if (x > -50 && this.swiped !== WHITE) {
swiped = WHITE;
} else if (x < -50 && x > -threshold && this.swiped !== GREEN) {
swiped = GREEN;
}
if (swiped !== null) {
this.swiped = swiped;
Animated.timing(this.state.color, {
toValue: swiped,
duration: 200
}).start();
}
}
takeAction = () => {
if (this.swiped) {
Animated.timing(this.state.color, {
toValue: WHITE,
duration: 200
}).start();
this.props.onSwipe();
}
}
render() {
const { swipeEnabled, swipeMessage, children } = this.props;
const bgColor = this.state.color.interpolate({
inputRange: [
WHITE,
GREEN
],
outputRange: [
'rgb(255, 255, 255)',
'rgb(123, 204, 40)'
]
});
return (
<View>
<AnimatedScrollView
horizontal
directionalLockEnabled
automaticallyAdjustContentInsets={false}
onScroll={this.animateScroll}
scrollEventThrottle={16}
scrollEnabled={swipeEnabled}
onMomentumScrollBegin={this.takeAction}
style={[{ flex: 1 }, { backgroundColor: bgColor }]}>
<View>
<View {...style('itemContainer')}>
{children}
</View>
<View
{...style(
'swipeMessage',
[{ width: width / 5, right: -width / 5 - 20 }]
)}>
<Text {...style('text.bold text.white')}>{swipeMessage}</Text>
</View>
</View>
</AnimatedScrollView>
</View>
);
}
}
SwipeListRow.propTypes = {
children: React.PropTypes.node.isRequired,
onSwipe: React.PropTypes.func.isRequired,
swipeEnabled: React.PropTypes.bool.isRequired,
swipeMessage: React.PropTypes.string.isRequired
};
export default SwipeListRow;
有了这些组件,现在您所要做的就是像在 ListView component documentation.
中描述的那样将所需的数据源传递给普通列表视图 <SwipeList
dataSource={dataSource}
renderRow={(item) => (
<SwipeListRow
key={item.id}
swipeMessage={'Delete Item'}
onSwipe={() => deleteItem(item)}
swipeEnabled={true}>
<<< INSERT DISPLAY OF ROW HERE >>>
</SwipeListRow>
)} />
用这个
这真的很好用,你可以扩展到任何东西。