前言
这篇文章没有什么特别需要讲的,主要是之前在处理键盘遮挡问题的时候,使用到了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表示与上端持平.