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

原文链接 https://blog.csdn.net/qq_22329521/article/details/81987595

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

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

效果如下


1535026425(1).png

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容