ios - React Native - 当键盘显示时调整 ScrollView (ios)

标签 ios react-native react-native-ios react-animated

在我的聊天应用程序中,当键盘从 View 底部显示时,我无法将 ScrollView (聊天 View )动画化以向上滑动/调整。

如果您使用过任何主流聊天应用程序,例如Messenger、微信、Line等,您将看到随着键盘的出现,您的聊天屏幕会如何平滑地升起。现在,我模仿了 KeyboardAvoidingView 并实现了类似的东西:

// Triggered by Keyboard.addListener("keyboardWillChangeFrame", onKeyboardChange);
  const onKeyboardChange = e => {
    if (!e) {
      //this is scroll view's contentInset.top
      setSpacing(0);
      return;
    }

    const { duration, easing, endCoordinates, startCoordinates } = e;
    let offset;
    if (startCoordinates) {
      offset = startCoordinates.screenY - endCoordinates.screenY;
    } else {
      offset = endCoordinates.height;
    }

    const spacing = offset > 0 ? offset : 0;
    if (duration && easing) {
      LayoutAnimation.configureNext({
        // We have to pass the duration equal to minimal accepted duration defined here: RCTLayoutAnimation.m
        duration: duration > 10 ? duration : 10,
        update: {
          duration: duration > 10 ? duration : 10,
          type: LayoutAnimation.Types[easing] || "keyboard"
        }
      });
    }
    //this is scroll view's contentInset.top
    setSpacing(spacing);
  };

如您所见,我目前只是使用 KeyboardWillChangeFrame 传递的事件计算偏移量,并使用 LayoutAnimation 来动画 ScrollView 向上滑动。 它工作得相当好,但我仍然可以看到轻微的延迟。

在原生iOS开发中,可以使用 animateKeyframes 来实现:

@objc func keyboardWillShow(notification: NSNotification){
    let duration = notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! Double
    let curve = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! UInt
    let curFrame = (notification.userInfo![UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    let targetFrame = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let deltaY = targetFrame.origin.y - curFrame.origin.y

    UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIView.KeyframeAnimationOptions(rawValue: curve), animations: {
        self.view.frame.origin.y += deltaY
    })
}

但它似乎在 React Native 中不可用。 当键盘从底部显示时,我是否可以尽可能平滑地调整 ScrollView ?

最佳答案

你必须做两件事

1:首次使用react-native-keyboard-spacer使 Textinput 容器滚动

2:设置键盘显示/隐藏时ChatList的偏移量

完整代码

import React from "react";
import { View, FlatList, Text, TextInput, Keyboard } from "react-native";
import KeyboardSpacer from "react-native-keyboard-spacer";

export default class App extends React.Component {
  state = {
    chat: [
      { id: 1, text: "Test1 1" },
      { id: 2, text: "Test1 2" },
      { id: 3, text: "Test1 3" },
      { id: 4, text: "Test1 4" },
      { id: 5, text: "Test1 5" },
      { id: 6, text: "Test1 6" },
      { id: 7, text: "Test1 7" },
      { id: 8, text: "Test1 8" },
      { id: 9, text: "Test1 9" },
      { id: 10, text: "Test1 10" },
      { id: 11, text: "Test1 11" },
      { id: 12, text: "Test1 12" },
      { id: 13, text: "Test1 13" },
      { id: 14, text: "Test1 14" },
      { id: 15, text: "Test1 15" },
      { id: 16, text: "Test1 16" },
      { id: 17, text: "Test1 17" },
      { id: 18, text: "Test1 18" },
      { id: 19, text: "Test1 19" },
      { id: 20, text: "Test1 20" },
      { id: 21, text: "Test1 21" },
      { id: 22, text: "Test1 22" },
      { id: 23, text: "Test1 23" },
      { id: 24, text: "Test1 24" }
    ]
  };

  scrollOffset = 0;
  keyboardHeight = 0;

  componentDidMount() {
    this.keyboardWillShowListener = Keyboard.addListener(
      "keyboardWillShow",
      this._keyboardWillShow
    );
    this.keyboardWillHideListener = Keyboard.addListener(
      "keyboardWillHide",
      this._keyboardWillHide
    );
  }

  componentWillUnmount() {
    this.keyboardWillShowListener.remove();
    this.keyboardWillHideListener.remove();
  }

  _keyboardWillShow = e => {
    this.keyboardHeight = e.endCoordinates
      ? e.endCoordinates.height
      : e.end.height;

    const newOffset = this.scrollOffset + this.keyboardHeight;
    this.chatList.scrollToOffset({ offset: newOffset, animated: true });
  };

  _keyboardWillHide = e => {
    const newOffset = this.scrollOffset - this.keyboardHeight;
    this.chatList.scrollToOffset({ offset: newOffset, animated: true });
  };

  handleScroll = e => {
    this.scrollOffset = e.nativeEvent.contentOffset.y;
  };

  render() {
    return (
      <View style={{ flex: 1, marginTop: 30 }}>
        <FlatList
          style={{ flex: 1 }}
          ref={ref => {
            this.chatList = ref;
          }}
          data={this.state.chat}
          renderItem={({ item }) => (
            <Text style={{ padding: 20 }}>{item.text}</Text>
          )}
          onScroll={this.handleScroll}
        />
        <TextInput
          placeholder="Enter Message"
          style={{ padding: 20, borderTopWidth: 1, borderColor: "black" }}
        />
        <KeyboardSpacer />
      </View>
    );
  }
}

应用预览

enter image description here

关于ios - React Native - 当键盘显示时调整 ScrollView (ios),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57831165/

相关文章:

android - 如何为ibeacons设置坐标?

react-native - 有没有办法在 React Native 中为 TextInput 做 letterSpacing?

react-native - 如何刷新 react native 平面列表上的特定行?

react-native - react 导航标题包装

ios - 旧版 iOS 上的 Google Maps SDK

ios - 带有表情符号的属性字符串 - 适当的高度

javascript - React Native,如何删除旧样式并添加新样式

javascript - React Native Expo 音频播放器错误 - 播放器不存在

ios - 应用程序 ID(团队 ID)

javascript - 如何为所有页面中的导航栏设置通用颜色(react native)使用createStackNavigator进行导航