Я использую React Natives KeyboardAvoidingView, чтобы установить высоту моего View, когда отображается клавиатура. Но когда я закрываю клавиатуру в приложении, высота просмотра не возвращается к исходному значению.

<KeyboardAvoidingView behavior="height" style={styles.step}>
  <View style={styles.stepHeader}>
    // my content
  </View>
</KeyboardAvoidingView>

Вид с красным контуром занял все пространство, прежде чем я открыл и закрыл клавиатуру.

Screenshot

21
mxmtsk 12 Янв 2017 в 18:05

4 ответа

Лучший ответ

Более подробное объяснение ответа Нисарга.

Создайте ключ для 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, я не совсем уверен, почему, я обновлю ответ после более глубокого исследования), так что вы придется отслеживать любые значения состояния / проп, которые могут быть перезаписаны

Обновить

После гораздо более глубокого расследования я теперь знаю, почему представления воссоздаются, когда вы меняете ключ.Чтобы по-настоящему понять, почему это происходит, нужно знать, как реагирующий-нативный отправляет команды рендеринга нативной стороне. Это конкретное объяснение довольно длинное, если оно вас интересует, вы можете прочитать мой ответ . Короче говоря ,act-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, которая, как указано выше, создает все элементы, вложенные в указанный компонент.

22
Samer Murad 8 Ноя 2018 в 08:57

Простой обходной путь - установить для свойства behavior KeyboardAvoidingView значение 'padding'. Это позволяет избежать вызова функции constructor, которая позволяет безопасно хранить информацию в состоянии (скажем, у вас есть два Input, и вы хотите сохранить значение текста в состоянии, даже если пользователь сворачивает клавиатуру между нажатиями двух входов).

Этот метод может немного изменить расположение дочерних элементов KeyboardAvoidingView, так что помните об этом.

0
Rainbow Fossil 3 Апр 2019 в 17:54

Обернуть компоненты в <KeyboardAvoidingView behavior="padding" style={styles}> на iOS и <View style={styles}> на Android

render() {
    const ScrollContainer: View | KeyboardAvoidingView = 
    this.renderDependingOnPlatform();
    const scrollContainerParams: any = {};
    if (isIOS)
        scrollContainerParams.behavior = "padding";
return (
<ScrollContainer style={styles.container} {...scrollContainerParams}>
Scroll and other components
</ScrollContainer>
)}

/**
 * Render scroll container depending on platform
 * @returns {any}
 */
renderDependingOnPlatform() {
    if (isAndroid())
        return View;
    else return KeyboardAvoidingView;
}
2
Daniel Zara 12 Мар 2019 в 14:10

Пожалуйста, дайте ключ к KeyboardAvoidingView и измените, когда клавиатура откроется и закроется, чтобы она отображалась и принимала высоту

<KeyboardAvoidingView behavior="height" style={styles.step} key={values}>
7
Nisarg Thakkar 8 Июл 2017 в 05:09