Ответ 1
Более подробное объяснение ответа Нисарга.
Создайте ключ для KeyboardAvoidingView
в конструкторе
constructor(props) {
this.state = {
keyboardAvoidingViewKey: 'keyboardAvoidingViewKey',
}
}
добавить слушатель на клавиатуре будет/действительно скрыть (и удалить его в волеизключении)
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
в функции keyboardHideListener
, каждый раз должно быть новое значение (я использовал временную метку) и используйте эту клавишу при рендеринге элемента KeyboardAvoidingView
.
keyboardHideListener() {
this.setState({
keyboardAvoidingViewKey:'keyboardAvoidingViewKey' + new Date().getTime()
});
}
render() {
let { keyboardAvoidingViewKey } = this.state
return (
<KeyboardAvoidingView behavior={'height'} key={keyboardAvoidingViewKey} style={...}>
...
</KeyboardAvoidingView>
)
}
Примечание: имейте в виду, что это будет воссоздавать элементы внутри KeyboardAvoidingView
(то есть: будет вызывать их функцию constructor
, я не совсем уверен, почему, я обновлю ответ после более глубокого исследования), так что вам придется отслеживать любого значения состояния/пропа, которые могут быть перезаписаны
Обновить
После гораздо более глубокого исследования я теперь знаю, почему представления воссоздаются, когда вы меняете ключ. Чтобы по-настоящему понять, почему это происходит, нужно знать, как реагирующий-нативный отправляет команды рендеринга нативной стороне, это конкретное объяснение довольно длинное, и если оно вас интересует, вы можете прочитать мой ответ здесь. Короче говоря, response-native использует Reactjs для сравнения изменений, которые должны быть отображены, затем эти различия отправляются в виде команд компоненту с именем UIManager
, который отправляет императивные команды, которые преобразуются в дерево макетов, которое меняет макет на основе команд diff, После того, как вы установили ключ для компонента, activjs использует этот ключ для определения изменений в указанном компоненте. Если этот ключ изменяется, реагирует, что компонент идентифицирует компонент как совершенно новый, который, в свою очередь, отправляет начальную команду для создания указанного компонента, делая все это дочерние элементы, которые будут созданы с нуля, потому что они идентифицируются как новые элементы в новом дереве макета, удаляя старое дерево и создавая новое вместо простой настройки различий.
Если вы хотите, вы можете шпионить за этими отправленными сообщениями, добавив следующий код в ваш файл App.js
:
import MessageQueue from 'react-native/Libraries/BatchedBridge/MessageQueue'
const spyFunction = (msg) => {
console.log(msg);
};
MessageQueue.spy(spyFunction);
Если вы сделаете это, в журналах вы заметите, что при каждом изменении ключа возвращаемая createViews
- это createViews
, которая, как указано выше, создает все элементы, вложенные в указанный компонент.