【问题标题】:KeyboardAvoidingView - Reset height when Keyboard is hiddenKeyboardAvoidingView - 隐藏键盘时重置高度
【发布时间】:2017-05-27 18:05:39
【问题描述】:

当显示键盘时,我正在使用 React Natives KeyboardAvoidingView 设置我的 View 的高度。但是当我在应用程序中关闭键盘时,视图的高度并没有变回原来的值。

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

在我打开和关闭键盘之前,带有红色轮廓的视图确实占据了整个空间。

【问题讨论】:

标签: javascript ios react-native keyboard


【解决方案1】:

请给 KeyboardAvoidingView 键并在键盘打开和关闭时进行更改,以便它呈现并占用高度

<KeyboardAvoidingView behavior="height" style={styles.step} key={values}>

【讨论】:

  • 拯救了我的一天!谢谢! :)
  • @diofeher 请阅读 Samer Murad 的回答,他描述了我的回答,人们可以理解。谢谢..!!
【解决方案2】:

关于Nisarg的回答更详细的解释。

在构造函数中为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()
}

更新keyboardHideListener函数中的keyboardAvoidingViewKey,每次都应该是一个新值(我使用了时间戳)并在渲染KeyboardAvoidingView元素时使用这个键。

keyboardHideListener() {
    this.setState({
        keyboardAvoidingViewKey:'keyboardAvoidingViewKey' + new Date().getTime()
    });
}

render() {
    let { keyboardAvoidingViewKey } = this.state
    return (
        <KeyboardAvoidingView behavior={'height'} key={keyboardAvoidingViewKey} style={...}>
            ...
        </KeyboardAvoidingView>
    )
}

注意: 请记住,这将重新创建 KeyboardAvoidingView 中的元素(即:将调用他们的 constructor 函数,我不太清楚为什么,我会在更深入的调查后更新答案),所以你必须跟踪可能被覆盖的任何状态/属性值

更新

经过更深入的调查,我现在知道为什么在更改密钥后会重新创建视图。 要真正理解为什么会这样,必须熟悉 react-native 是如何将渲染命令分发到原生端的,这个解释很长,如果你感兴趣,可以阅读我的回答 here。简而言之,react-native 使用 Reactjs 来区分应该呈现的更改,然后将这些差异作为命令发送到名为 UIManager 的组件,该组件发送转换为布局树的命令式命令,它根据差异命令。 一旦你在一个组件上设置了一个键,reactjs 就会使用这个键来识别对所述组件的更改,如果这个键发生了变化,reactjs 会将该组件识别为一个全新的组件,作为回报,它会发送初始命令来创建所述组件,使其成为要从头开始创建子元素,因为在新布局树中被标识为新元素,删除旧树并创建新树,而不仅仅是调整差异

如果您愿意,您实际上可以通过将以下代码添加到您的 App.js 文件中来监视这些发送的消息:

import MessageQueue from 'react-native/Libraries/BatchedBridge/MessageQueue'
const spyFunction = (msg) => {
    console.log(msg);
};

MessageQueue.spy(spyFunction);

如果您这样做,您会在日志中注意到每次键更改时,返回的命令是createViews,如上所述,它会创建嵌套在所述组件下的所有元素。

【讨论】:

  • 感谢您的详细解释。如果您发现它为什么会重新创建元素,我将不胜感激并更新您的答案!
  • 在我的情况下,键盘并没有消失,不断地上下弹出。
  • 这可能是另一种问题,您遇到的情况,此代码不会影响键盘,只会影响隐藏在键盘后面的布局,阅读问题,它说 > 当我关闭应用中的键盘,View的高度不会变回原来的值。
  • 工作就像一个魅力。谢谢!
  • 如果你得到this.setState is not a function,将componentDidMount中的this.keyboardHideListener更改为this.keyboardHideListener.bind(this)
【解决方案3】:

在 iOS 上将组件包装在 &lt;KeyboardAvoidingView behavior="padding" style={styles}&gt; 中,在 Android 上将组件包装在 &lt;View style={styles}&gt;

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;
}

【讨论】:

    【解决方案4】:

    一个简单的解决方法是将KeyboardAvoidingViewbehavior 属性设置为“填充”。这避免了调用 constructor 函数的问题,该函数允许您安全地将信息存储在 state 中(假设您有两个 Inputs 并且您希望将文本的值存储在 state 中,即使用户折叠键盘在单击两个输入之间)。

    此方法可能会稍微改变KeyboardAvoidingView 的子元素的布局,因此请注意这一点。

    【讨论】:

    • 这为我解决了问题。布局已更改,但高度偏移来自我隐藏的标签栏,因此很容易修复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 2020-10-12
    • 2011-09-20
    相关资源
    最近更新 更多