react-native 之SwipeableFlatList 侧滑单项解决方案

react-native 侧滑组件SwipeableFlatList 单项侧滑解决

SwipeableFlatList 组件是 rn 0.50 出的 提供android ios 侧滑删除

效果如下
这里写图片描述
//ui 网上copy代码
ui 参考https://blog.csdn.net/yu_m_k/article/details/80580250 拷贝下来的

/**
 * 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>

//如有理解有误 敬请谅解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值