React-Native RN 列表拖拽交换Item功能
开发米家项目使用RN框架,需要要写一个手法编辑可拖动删除的组件页面,记录一下;
可按住右边图标进行拖动,左边删除图标删除当前项
//这里可根据需要引用
import React from 'react';
import {
Image, View, Text,StyleSheet,TouchableOpacity,PanResponder } from 'react-native';
import NavigationBar from 'miot/ui/NavigationBar';
import common from "../../resources/css/common";
import {
AbstractDialog,LoadingDialog } from "miot/ui/Dialog";
import {
RkButton,RkText } from "react-native-ui-kitten";
import PluginStrings from "../../resources/strings";
export default class MassageTechniqueEditor extends React.Component {
/**
* 页面内部自定义Header
* @param navigation
* @returns {
{header: *}|{header: null}}
*/
static navigationOptions = ({
navigation }) => {
const {
titleProps } = navigation.state.params || {
};
if (!titleProps) return {
header: null };
return {
header: <NavigationBar {
...titleProps} />
};
};
constructor(props) {
super(props);
this.initNavigationBar()
this.state={
names:[{
method:'肩部',
effots:'50',//力度
info:'指压'
},{
method:'颈部',
effots:'30',//力度
info:'指压'
},{
method:'手部',
effots:'40',//力度
info:'指压'
},{
method:'脚部',
effots:'60',//力度
info:'指压'
},{
method:'肩部',
effots:'50',//力度
info:'指压'
},{
method:'颈部',
effots:'30',//力度
info:'指压'
},{
method:'手部',
effots:'40',//力度
info:'指压'
},{
method:'脚部',
effots:'60',//力度
info:'指压'
}]
}
this.items = [];
this.order = [];
}
initNavigationBar() {
this.props.navigation.setParams({
titleProps: {
left: [
{
key: NavigationBar.ICON.CLOSE,
onPress: () => {
this.setState({
visible: true,
});
},
},
],
right: [
{
key: NavigationBar.ICON.COMPLETE,
onPress: () => {
this.setState({
loadingVisiable:true
})
},
},
],
}
});
}
render(){
return(
<View style={
styles.container}>
<Text style={
common.navTit}>手法编辑</Text>
{
this.state.names.map((item, i)=>{
this.order.push(item);
return (
<View
ref={
(ref) => {
this.items[i] = ref
}}
key={
i}
style={
[styles.item, {
top: (i+1)*72}]}>
<View style={
{
flexDirection: 'row',alignItems:'center'}}>
<TouchableOpacity
style={
{
width:22,height:22}}
onPress={
()=>{
const arrs= this.state.names;
arrs.splice(i,1);
this.setState({
names:arrs
});
}}
>
<Image
style={
{
width:22,height:22}}
source={
require("../../resources/images/delete1.png")}
/>
</TouchableOpacity>
<Image
style={
styles.imgbody}
source={
require("../../resources/images/icon/rubItOn.png")}
/>
<View style={
{
marginLeft:12}}>
<Text style={
{
fontSize:16,color:'#000'}}>{
item.method}</Text>
<Text style={
{
fontSize:13,color:'rgba(0,0,0,0.6)'}}>{
item.info} | 力度{
item.effots}</Text>
</View>
</View>
<Image
{
...this._panResponder.panHandlers}//根据手势拖动方法来实现,可根据需求把此方法放到需要可拖动的地方
style={
{
width:22,height:22}}
source={
require("../../resources/images/sort.png")}
/>
</View>
);
})}
</View>
);
}
componentWillMount(){
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,//开启手势响应
onMoveShouldSetPanResponder: (evt, gestureState) => true,//开启移动手势响应
onPanResponderGrant: (evt) => {
//手指触碰屏幕那一刻触发
const {
pageY, locationY} = evt.nativeEvent;
let num=pageY
num=num-70
this.index = this._getIdByPosition(num);
this.preY = num - locationY;
//get the taped item and highlight it
if(this.index==-1){
return false
}
let item = this.items[this.index];
item.setNativeProps({
style: {
shadowColor: "#000",
shadowOpacity: 0.3,
shadowRadius: 5,
shadowOffset: {
height: 0, width: 2},
elevation: 5
}
});
},
onPanResponderMove: (evt, gestureState) => {
//手指在屏幕上移动触发
let top = this.preY + gestureState.dy;
if(this.index==-1){
return false
}
let item = this.items[this.index];
item.setNativeProps({
style: {
top: top}
});
let collideIndex = this._getIdByPosition(evt.nativeEvent.pageY);
if(collideIndex !== this.index && collideIndex !== -1) {
let collideItem = this.items[collideIndex];
collideItem.setNativeProps({
style: {
top: this._getTopValueYById(this.index)}
});
//swap two values
[this.items[this.index], this.items[collideIndex]] = [this.items[collideIndex], this.items[this.index]];
[this.order[this.index], this.order[collideIndex]] = [this.order[collideIndex], this.order[this.index]];
this.index = collideIndex;
}
},
onPanResponderTerminationRequest: (evt, gestureState) => true,//当有其他不同手势出现,响应是否中止当前的手势
onPanResponderRelease: (evt, gestureState) => {
//手指离开屏幕触发
const shadowStyle = {
shadowColor: "#000",
shadowOpacity: 0,
shadowRadius: 0,
shadowOffset: {
height: 0, width: 0,},
elevation: 0
};
if(this.index==-1){
return false
}
let item = this.items[this.index];
//go back the correct position
item.setNativeProps({
style: {
...shadowStyle, top: this._getTopValueYById(this.index)}
});
},
onPanResponderTerminate: (evt, gestureState) => {
//当前手势中止触发
// Another component has become the responder, so this gesture
// should be cancelled
}
});
}
_getIdByPosition(pageY){
var id = -1;
const height = 72;
if(pageY >= height && pageY < height*2)
id = 0;
else if(pageY >= height*2 && pageY < height*3)
id = 1;
else if(pageY >= height*3 && pageY < height*4)
id = 2;
else if(pageY >= height*4 && pageY < height*5)
id = 3;
else if(pageY >= height*5 && pageY < height*6)
id = 4;
else if(pageY >= height*6 && pageY < height*7)
id = 5;
else if(pageY >= height*7 && pageY < height*8)
id = 6;
else if(pageY >= height*8 && pageY < height*9)
id = 7;
else if(pageY >= height*9 && pageY < height*10)
id = 8;
else if(pageY >= height*10 && pageY < height*11)
id = 9;
else if(pageY >= height*11 && pageY < height*12)
id = 10;
else if(pageY >= height*12 && pageY < height*13)
id = 11;
else if(pageY >= height*13 && pageY < height*14)
id = 12;
else if(pageY >= height*14 && pageY < height*15)
id = 13;
else if(pageY >= height*15 && pageY < height*16)
id = 14;
return id;
}
_getTopValueYById(id){
const height = 72;
return (id + 1) * height;
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor:'#fff',
paddingHorizontal:12
},
item: {
paddingHorizontal:20,
flexDirection: 'row',
height:72,
width: '100%',
alignItems: 'center',
justifyContent:'space-between',
backgroundColor: '#fff',
borderBottomColor: 'rgba(232,232,232,0.42)',
borderBottomWidth: 1,
position: 'absolute',
},
imgbody: {
resizeMode: "contain",
height: 36,
width: 36,
marginLeft: 10,
},
})