显示键盘

时间:2017-05-17 01:20:44

标签: react-native

我在KeyboardAvoidingView中有一个FlatList。当键盘显示时,我想滚动到FlatList的末尾。

我正在聆听键盘上的演出'被触发的事件,但由于FlatList在调用scrollToEnd后没有滚动到最后,因此可能会被触发太早。

我已经查看了KeyboardAvoidingView的onLayout事件,但只是设置onLayout事件来触发一个函数似乎阻止了KeyboardAvoidingView在显示键盘时调整它的大小。

<KeyboardAvoidingView behavior='padding' style={{ flex: 1}} onLayout={this._scrollEnd}>

代码:

import React from 'react';
import {Image, Linking, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, View, Button, Alert, FlatList, TextInput, KeyboardAvoidingView, Keyboard} from 'react-native';
import { MonoText } from '../components/StyledText';

export default class HomeScreen extends React.Component {
  constructor() {
    super();
    this.state = {
      messages: getMessages()
    };

    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._scrollEnd);
    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidHide', this._scrollEnd);
  }

  _scrollEnd = (evt) => {
    this.refs.flatList1.scrollToEnd();
  }

  render() {
    return (
      <KeyboardAvoidingView behavior='padding' style={{ flex: 1}} >
        <FlatList
          style={{ flex:1}}
          ref="flatList1"
          data={this.state.messages}
          renderItem={({ item }) => <Text>{item.text}</Text>}
        />
      </KeyboardAvoidingView>
    );
  }
}

5 个答案:

答案 0 :(得分:25)

我正在制作聊天组件,我想要同样的事情。它是这样的:

#!/Users etc
import re,sys,os.path,pip,os.path
import webbrowser

def press_key(key):
    cmd = "osascript -e 'tell application \"System Events\" to keystroke \"" + key + "\"'"
    os.system(cmd)

b=webbrowser.get('safari')
b.open('google.com') and press_key("hello")

键盘弹出会触发布局,以便修复。到达的新聊天消息会触发内容更改,因此它也会滚动到底部(这是我想要的聊天窗口)

答案 1 :(得分:20)

实际上如果你总是想滚动到最后,意味着你总是希望看到最新的消息,我是对的吗?

然后使用新版本的react-native。并添加倒置以更改平面列表的倒置。

<FlatList
      inverted
      style={{ flex:1}}
      ref="flatList1"
      data={this.state.messages}
      renderItem={({ item }) => <Text>{item.text}</Text>}
    />

然后将您的 this.state.messages 重新排列。那么您的最新消息将始终显示在平面列表的底部

就我而言,我不需要使用 KeyboardAvoidingView

答案 2 :(得分:1)

一些用户 (@Nathileo) 要求使用基于钩子的方法滚动到 FlatList 的末尾。

  1. 首先,你需要实现 React 的 useRef 钩子:

    import {useRef} from 'react';

    const yourRef = useRef(null);

  2. 其次,FlatList 标签必须配备一个引用和所需的功能:

    <FlatList
      ref={yourRef}
      onContentSizeChange={() => yourRef.current.scrollToEnd() }
      onLayout={() => yourRef.current.scrollToEnd() }
    />
    

答案 3 :(得分:0)

如上文comment所述,getItemLayout应解决您的问题。

根据Reactive FlatList documentation

  

getItemLayout是一个可选的优化,如果您事先知道项目的高度,我们就可以跳过动态内容的测量。 getItemLayout是最有效的,如果您有固定的高度项,则易于使用,例如:

getItemLayout={(data, index) => (
  {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
)}

如果您使用ItemSeparatorComponent,请不要忘记在计算结果偏移量时合并分隔符的高度或宽度。

答案 4 :(得分:0)

我一直在使用这个用键盘管理平板高度的小组件。这使用了renderProps模式,因此您可以重用它:)

import { PureComponent } from 'react';
import { Keyboard, Dimensions, Animated } from 'react-native';

const DURATION = 200;

class ListSpacer extends PureComponent {
  state = {
    screenHeight: Dimensions.get('window').height,
    flatListHeight: new Animated.Value(Dimensions.get('window').height),
  };

  componentDidMount() {
    this._keyboardDidShowListener = Keyboard.addListener(
      'keyboardDidShow',
      this._keyBoardDidShow,
    );
    this._keyboardDidHideListener = Keyboard.addListener(
      'keyboardDidHide',
      this._keyBoardDidHide,
    );
  }

  componentWillUnmount() {
    this._keyboardDidShowListener.remove();
    this._keyboardDidHideListener.remove();
  }

  _keyBoardDidShow = e => {
    Animated.timing(this.state.flatListHeight, {
      toValue: Dimensions.get('window').height - e.endCoordinates.height,
      duration: DURATION,
    }).start();
  };

  _keyBoardDidHide = () => {
    Animated.timing(this.state.flatListHeight, {
      toValue: Dimensions.get('window').height,
      duration: DURATION,
    }).start();
  };

  render() {
    const renderProps = {
      flatListHeight: this.state.flatListHeight,
    };

    if (this.props.children) {
      return this.props.children(renderProps);
    }

    return this.props.render(renderProps);
  }
}

export default ListSpacer;

我们在这里听键盘事件,并且endcoordinates给你键盘高度。这样你就可以用它来制作平面列表高度。

import {
  FlatList,
  KeyboardAvoidingView,
  Animated,
} from 'react-native';

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);

return (
  <ListSpacer>
    {({ flatListHeight }) => (
      <KeyboardAvoidingView
        behavior="padding"
        keyboardVerticalOffset={INPUT_HEIGHT}
      >
        <AnimatedFlatList
          inverted
          style={{ height: flatListHeight }}
          data={data.comments}
          keyExtractor={this._keyExtractor}
          renderItem={this._renderItem}
          contentContainerStyle={styles.contentList}
        />
      </KeyboardAvoidingView>
    )}
  </ListSpacer>
);

在这里,我有这个教程,我展示了如果你更具视觉效果:)

https://youtu.be/2QnPZXCIN44?t=28m43s