前言
這篇文章沒有什么特別需要講的,主要是之前在處理鍵盤遮擋問題的時候,使用到了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
必須要配合flatlist
的getItemLayout
設置.
片段一
<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表示與上端持平.