react-native 之SwipeableFlatList 側(cè)滑單項解決方案

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

react-native 側(cè)滑組件SwipeableFlatList 單項側(cè)滑解決

SwipeableFlatList 組件是 rn 0.50 出的 提供android ios 側(cè)滑刪除

效果如下


1535026425(1).png

//ui 網(wǎng)上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數(shù)據(jù)的獲取和渲染
          data={CITY_NAMES}
          renderItem={(data) => <View style={styles.item}>
            <Text style={styles.text}>{data.item}</Text>
          </View>}

          //2創(chuàng)建側(cè)滑菜單
          renderQuickActions={() => this.getQuickActions()}//創(chuàng)建側(cè)滑菜單
          maxSwipeDistance={80}//可展開(滑動)的距離
          bounceFirstRowOnMount={false}//進(jìn)去的時候不展示側(cè)滑效果
        />
      </View>
    );
  }
  //側(cè)滑菜單渲染
  getQuickActions = () => {
    return <View style={styles.quickAContent}>
      <TouchableHighlight
        onPress={() => alert("確認(rèn)刪除?")}
      >
        <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,
  },
  //側(cè)滑菜單的樣式
  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 說明不提供關(guān)閉側(cè)滑功能 以及只支持單個側(cè)滑(及打開一個側(cè)滑關(guān)閉上面的側(cè)滑)
分析源碼

在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);

//就有無側(cè)滑
    // 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}
        //這里我們看到他實際上是每個打開關(guān)閉都是有的但是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 更新會出處罰這關(guān)閉item
    if (this.props.isOpen && !nextProps.isOpen) {
      this._animateToClosedPosition();
    }
  },

看了什么實際上SwipeableFlatList 是做了只支持單項了操作但是為什么能開啟多個側(cè)滑那
原因在于flatlist 的data 是數(shù)組引用問題 data如果引用不變是不會觸發(fā)flatlist的刷新

這里就需要用到一個 flatlist extraData 的屬性

extraData
如果有除data以外的數(shù)據(jù)用在列表中(不論是用在renderItem還是頭部或者尾部組件中),請在此屬性中指定。同時此數(shù)據(jù)在修改時也需要先修改其引用地址(比如先復(fù)制到一個新的 Object 或者數(shù)組中),然后再修改其值,否則界面很可能不會刷新。

我們修改源碼

 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}
            />
        );
    }
}

還有 當(dāng)你單擊完手動關(guān)閉側(cè)滑 我們看到 SwipeableFlatList 是提供了 我們自己使用引用去手動調(diào)關(guān)閉方法

_onClose(key: any): void {
    this.setState({
      openRowKey: null,
    });

手動關(guān)閉側(cè)滑

<SwipeableFlatList
          //1數(shù)據(jù)的獲取和渲染
          data={CITY_NAMES}
          renderItem={(data) => <View style={styles.item}>
            <Text style={styles.text}>{data.item}</Text>
          </View>}
 ref={ref => {
  this._flatListRef = ref;
}}
          //2創(chuàng)建側(cè)滑菜單
          renderQuickActions={() => this.getQuickActions()}//創(chuàng)建側(cè)滑菜單
          maxSwipeDistance={80}//可展開(滑動)的距離
          bounceFirstRowOnMount={false}//進(jìn)去的時候不展示側(cè)滑效果
        />

  <TouchableHighlight
        onPress={() =>this._flatListRef._onClose()}
      >
        <View style={styles.quick}>
          <Text style={styles.delete}>刪除</Text>
        </View>
      </TouchableHighlight>

//如有理解有誤 敬請諒解

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容