React Native 踩坑日记(十) —— 使用 flatlist 的滚动处理键盘遮挡的问题.

前言

这篇文章没有什么特别需要讲的,主要是之前在处理键盘遮挡问题的时候,使用到了flatlist中的滚动问题,所以特别记录一下.

效果图

这种方案最后没有使用,原因有几个:

  • 只有 ios 下可以使用,因为在安卓系统上,如果输入框是最后一行的 cell, 让他往上滚动,是无法让该 cell 的顶部与页面的顶部持平的.(可以看上面的效果图)
  • 在安卓系统下,如果输入框是最底下那一行,点击后键盘弹出,还未滚动到顶部,键盘就立刻又消失了.
  • 这种做法的用户体验并不好,页面给人感觉会有大幅度的自行滚动.

之所以特意写了一篇笔记记录,主要是在这种方案中学到了几个东西.
下面是几个代码片段,一一说明.


实现思路

整个实现的目的,综合来说,就是

  • Textinput里头,当点击输入框时,产生了onFocus的回调,此时先让选中的cell滚动到整个页面的顶部.
  • 滚动必须调用到 flatlist 的scrollToIndex的方法,this._tableview.scrollToIndex({animated: true, index: cellIndex, viewPosition: 0});, viewPosition 为0表示让他的上部与顶部持平.
  • 输入结束后,获取到onEndEdit,再让他滚动到居中的位置,避免最后一行的空白问题.this._tableview.scrollToIndex({animated: true, index: cellIndex, viewPosition: 0.5});
  • 使用scrollToIndex必须要配合flatlistgetItemLayout设置.

片段一

 this._tableview = flatlist)} data={this.dataSource}
          renderItem={({item}) => this._renderItem(item)}
          keyExtractor={(item) => item.index}
          ItemSeparatorComponent={(item) => this._seperator(item)}
          extraData={this.state}
          getItemLayout={(data, index) => {
              let length = this.dataSource[index].height;
              let totalOffset = 0;
              for (let i = 0; i < index; i++) {
                  totalOffset += this.dataSource[i].height + 1;
              }
              // console.log('当前偏移 =' + totalOffset);
              return {length: length, offset: totalOffset, index: index};
          }}
          onScrollBeginDrag={() => {
              if (!this.isNeedKeyborad) {
                  return;
              }

              this.isNeedKeyborad = false;
              dismissKeyboard();
          }}
/>
  • getItemLayout 最后要返回一个 JSON object
    这几个值必须要返回的.

    • length 是当前 cell 的高度,
    • offset 是整个 flatlist 的当前偏移量(需要如代码中写的,遍历这个 cell 之前所有的 cell 高度,叠加)
    • index, 当前 cell 的索引值

    return {length: length, offset: totalOffset, index: index};

  • onScrollBeginDrag 写这个是为了避免滚动时,最后一行被键盘遮挡. 因为onScrollBeginDrag和另一个回调的onScroll不同,后者代表的是所有的滚动事件(包括用户手动拖曳,以及我们调用 scrollToIndex时候的滚动),所以要监听到我们的手动滚动,必须要使用这个回调.

  • dismissKeyboard(); 这个是系统提供的库,用来让键盘消失用的.

    import dismissKeyboard from '../../../node_modules/react-native/Libraries/Utilities/dismissKeyboard';

片段二

// 按键输入回调, 写入 state 进行保存.
_onEndEditText = (cellIndex, stateName, text) => {
    this.isNeedKeyborad = true;
    this._tableview.scrollToIndex({animated: true, index: cellIndex, viewPosition: 0.5});
    this.setState({[stateName]: text});

    console.log('输入结束的文本 =' + text + '\n返回的 state 名' + stateName);
    console.log('------------------');
};

_onFocusInputCell = (cellIndex) => {
    this.isNeedKeyborad = true;
    let CustomLayoutAnimation = {
        duration: 800,
        create: {
            type: LayoutAnimation.Types.spring,
            property: LayoutAnimation.Properties.scaleXY,
        },
        update: {
            type: LayoutAnimation.Types.spring,
            property: LayoutAnimation.Properties.scaleXY,
        },
    };
    LayoutAnimation.configureNext(CustomLayoutAnimation);

    this._tableview.scrollToIndex({animated: true, index: cellIndex, viewPosition: 0});

};
  • LayoutAnimation只是一个动画,类似于我们ios[UIView animationWithDuration]
  • this._tableview.scrollToIndex主要说明下后面的viewPosition参数,传入的是0到1之间的数.用来控制 cell 在当前滑动区域的位置.0表示与上端持平.

你可能感兴趣的:(React Native 踩坑日记(十) —— 使用 flatlist 的滚动处理键盘遮挡的问题.)