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設置.

片段一

<FlatList ref={(flatlist => 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表示與上端持平.
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容