【问题标题】:React Native - adjust scrollview as keyboard shows up (ios)React Native - 在键盘出现时调整滚动视图(ios)
【发布时间】:2019-09-07 06:06:16
【问题描述】:

在我的聊天应用程序中,当键盘从视图底部向上显示时,我无法为滚动视图(聊天视图)设置动画以向上滑动/调整。

如果您使用过任何主要的聊天应用程序,例如 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 为滚动视图上滑设置动画。 它工作得相当好,但我仍然可以看到轻微的延迟。

在原生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
    })
}

但它似乎在本机反应中不可用。 无论如何我可以调整滚动视图,因为键盘从底部尽可能平滑地显示?

【问题讨论】:

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


    【解决方案1】:

    你必须做两件事

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

    应用预览

    【讨论】:

    • @Hikaru Watanabe,更新了答案,添加了示例代码。请检查whatsapp,messanger等应用程序,它是底部文本输入视图,而不是聊天列表。聊天列表将保持相同的偏移量
    • 对不起,我想我把你弄糊涂了。我说的是聊天屏幕,例如您实际与人交谈的地方,而不是联系人列表。滚动视图包含对话,因此它需要在键盘出现时向上移动,以便用户在键盘出现时不会向下滚动以返回到他/她之前的位置
    • @Hikaru Watanabe 。我也在谈论聊天屏幕。请在 whatsapp 中再次检查。添加我制作的 whatapps 应用程序演示。检查此https://gph.is/g/ZnxYRkJ。当您要键入并打开键盘时,聊天列表将保持在同一位置。如果您添加新消息,聊天列表将移至底部
    • gph.is/g/ZnxYRkJ 正是我想要实现的。在gph.is/g/ZnxYRkJ 中,滚动视图偏移似乎随着键盘的出现而移动。但是在您的 AppPreview 中,flatlist/scrollview 似乎没有调整,这就是我使用您建议的开源时发生的情况。
    • 在你的app预览中,textinput自带键盘,但是scrollview contentView没有调整。
    猜你喜欢
    • 2013-04-09
    • 2019-02-08
    • 1970-01-01
    • 2014-08-20
    • 2020-08-20
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 2013-11-11
    相关资源
    最近更新 更多