更详细的解释Nisarg https://stackoverflow.com/users/4656866/nisarg-thakkar的回答。
为KeyboardAvoidingView
在构造函数中
constructor(props) {
this.state = {
keyboardAvoidingViewKey: 'keyboardAvoidingViewKey',
}
}
在键盘的 will/did hide 上添加侦听器(并在 willUnmount 中将其删除)
import { KeyboardAvoidingView, Keyboard, Platform } from 'react-native'
componentDidMount() {
// using keyboardWillHide is better but it does not work for android
this.keyboardHideListener = Keyboard.addListener(Platform.OS === 'android' ? 'keyboardDidHide': 'keyboardWillHide', this.keyboardHideListener.bind(this));
}
componentWillUnmount() {
this.keyboardHideListener.remove()
}
更新keyboardAvoidingViewKey
in the keyboardHideListener
函数,每次都应该是一个新值(我使用了时间戳)并在渲染时使用此键KeyboardAvoidingView
元素。
keyboardHideListener() {
this.setState({
keyboardAvoidingViewKey:'keyboardAvoidingViewKey' + new Date().getTime()
});
}
render() {
let { keyboardAvoidingViewKey } = this.state
return (
<KeyboardAvoidingView behavior={'height'} key={keyboardAvoidingViewKey} style={...}>
...
</KeyboardAvoidingView>
)
}
Note:请记住,这将重新创建内部的元素KeyboardAvoidingView
(即:将调用他们的constructor
函数,我不太确定为什么,我会在更深入的调查后更新答案),所以你必须跟踪任何可能被覆盖的状态/属性值
Update
经过更深入的调查后,我现在知道为什么一旦更改密钥就会重新创建视图。
为了真正理解为什么会发生这种情况,必须熟悉react-native如何将渲染命令分派到本机端,这个特定的解释很长,如果你感兴趣,你可以阅读我的答案here https://stackoverflow.com/a/48916954/2252297。简而言之,react-native 使用 Reactjs 来区分应该呈现的更改,然后将这些差异作为命令发送到名为的组件UIManager
,它发送转换为布局树的命令式命令,布局树根据 diff 命令更改布局。
一旦你在组件上设置了一个键,reactjs就会使用这个键来识别对所述组件的更改,如果这个键发生变化,reactjs会将该组件识别为一个全新的组件,作为回报,它会发送初始命令来创建所述组件,从而使其成为可能从头开始创建子元素,因为新布局树中被识别为新元素,删除旧树并创建新树,而不是仅仅调整差异
如果您愿意,您实际上可以通过将以下代码添加到您的App.js
file:
import MessageQueue from 'react-native/Libraries/BatchedBridge/MessageQueue'
const spyFunction = (msg) => {
console.log(msg);
};
MessageQueue.spy(spyFunction);
如果这样做,您会在日志中注意到每次键更改时,返回的调度命令是createViews
,如上所述,它创建了嵌套在所述组件下的所有元素。