React-Native RN 列表拖拽交换Item功能

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,
  },
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值