轉:
https://github.com/dwqs/blog/issues/39
在0.28版rn中,如果textinput的位置在靠近底部的位置,在textinput獲取焦點后,ios上彈出的鍵盤會遮住textinput,導致用戶無法輸入;android上彈出鍵盤時,整個界面會被網上頂,textinput不會被遮住。
在0.28中,解決ios上該問題的方式是利用 ScrollView contentInset 屬性,監聽鍵盤的彈出和隱藏事件(keyboardWillShow/keyboardWillHide),獲取鍵盤的高度,動態設置成 contentInset 的值。
將rn升級成0.33后,android和ios上都會出現TextInput 被鍵盤遮擋的問題,ios上原來的方式也不能解決此問題了。
在 ios 上,textinput 未獲取焦點前:
獲取焦點后:
textinput被鍵盤擋住了。android上有同樣的問題。
解決這種情況的一種方式,監聽鍵盤的彈出和隱藏事件,在ScrollView底部設置一個占位符組件,將占位符的高度設置成鍵盤的高度。
監聽鍵盤事件:
this.keyboardShow = Platform.OS === 'ios' ?
Keyboard.addListener('keyboardWillShow',this.updateKeyboardSpace.bind(this)) : Keyboard.addListener('keyboardDidShow',this.updateKeyboardSpace.bind(this));
this.keyboardHide = Platform.OS === 'ios' ?
Keyboard.addListener('keyboardWillHide',this.resetKeyboardSpace.bind(this)) : Keyboard.addListener('keyboardDidHide',this.resetKeyboardSpace.bind(this));
在事件處理程序中,獲取鍵盤高度:
updateKeyboardSpace(frames){
if(!frames.endCoordinates){
return;
}
let keyboardSpace = frames.endCoordinates.height;//獲取鍵盤高度
this.setState({
keyboardSpace: keyboardSpace
})
}
最后將高度傳遞給占位符組件:
<ScrollView>
//其他元素
<KeyboardSpacer keyboardSpace={this.state.keyboardSpace}/>
</ScrollView>
KeyboardSpacer組件實現如下:
const styles = StyleSheet.create({
container: {
left: 0,
right: 0,
bottom: 0
}
});
export default class KeyboardSpacer extends Component {
constructor(){
super();
}
static propTypes = {
keyboardSpace: PropTypes.number
};
static defaultProps = {
keyboardSpace: 0
};
render() {
let {keyboardSpace} = this.props;
return (
<View style={[styles.container, { height: ~~keyboardSpace }]} />
);
}
}
效果如下:
這樣子能解決部分場景,例如textInput的位置是靠近底部的。如果textinput框的位置是靠近頁面上部的,那么textinput框會被頂上去,就會因超出ScrollView的視口范圍而被“遮住”。
這時,就不能單純的將鍵盤的高度給 KeyboardSpacer 了,而應該根據textinput在ScrollView視口的位置進行 KeyboardSpacer 高度的計算了。
在頁面加載之后,能獲取到 ScrollView的視口高度ViewportHeight,這個值是保持不變的。此外,也能拿到textinput距離ScrollViewd頂邊的垂直距離InputY,這個值是固定的,不會隨着頁面的滾動而變化頁面示意如下:
在界面滾動一定距離之后,頁面示意如下:
紅邊表示此時ScrollView的頂邊位置,虛線框表示textInput框的原位置,實體框表示textInput在頁面滾動之后的位置。
頁面滾動時,能獲取到ScrollView已經滾動的偏移量 scrollY,此時,就能計算出此時 textInput 距離ScrollView視口底部的距離 InputToBottom:
InputToBottom = ViewportHeight - (InputY - scrollY + textInput的高度)
此時,應該根據InputToBottom與鍵盤高度的大小比較來設置 keyboardSpace:
keyboardHeight = frames.endCoordinates.height; //鍵盤高度
keyboardSpace = InputToBottom >= keyboardHeight ? 0 : keyboardHeight - InputToBottom;
在圖示頁面的布局中,還有一個底部元素,因而在計算 keyboardHeight 時,因考慮下實際情況是否需要減去底部元素的高度或者ScrollView的marginBottom值。