React Native需要两次点击才能在scrollview中更改输入焦点

时间:2016-04-07 12:42:37

标签: reactjs keyboard react-native

想象一下简单的ScrollView有多个TextInputs,比如

$.ajax({
  url: 'php/register-newuser.php',
  type: 'POST',
  data: formData,
  dataType: 'json', // This tells jQuery that it is getting JSON back - it will parse it for you
  async: false,
  cache: false,
  contentType: false,
  processData: false,
  success: function (data) {
    // data will be parsed by jQuery into an object or array based on the JSON
    console.log(data);
  },
});

当我输入第一个输入时,键盘打开,我可以输入文字。当我想要更改为第二个输入时,我需要两次点击 - 首先键入关闭键盘,然后只有第二个点击打开键盘进行第二次输入。

一种解决方案是使用 <ScrollView style={styles.container}> <TextInput style={styles.input} /> <TextInput style={styles.input} /> </ScrollView> - 切换工作正常然后键盘根本不关闭,键盘可以覆盖一些后来的输入(或按钮)。 我也可以使用keyboardShouldPersistTaps={true},但只需在拖动时关闭键盘。

我的问题是如何将这两种行为结合起来 - 进入恕我直言的最佳用户体验 - 当我点击另一个输入时,焦点立即改变而不重新打开键盘,当我点击其他地方键盘关闭时?

我正在使用RN0.22,样本申请可在https://rnplay.org/apps/kagpGw

获得

更新 - 此问题可能已在RN 0.40中解决 - 请参阅https://github.com/facebook/react-native/commit/552c60192172f6ec503181c060c08bbc5cbcc5a4

6 个答案:

答案 0 :(得分:3)

SO answer并不是您要求的,但当TextInput具有焦点时,会自动将窗口从键盘后面滑出;解析键盘可以覆盖一些后来的输入(或按钮)问题。

答案 1 :(得分:3)

最后,我找到了不是最优的解决方案(从编码角度来看),但从用户的角度来看。我制作了一个可用于代替ScrollView的小组件:

export class InputScrollView extends React.Component {

  constructor(props, ctx) {
      super(props, ctx);
      this.handleCapture = this.handleCapture.bind(this);
  }

  render() {
    return (
      <ScrollView keyboardShouldPersistTaps={true} keyboardDismissMode='on-drag'>
        <View onStartShouldSetResponderCapture={this.handleCapture}>
          {this.props.children}
        </View>
      </ScrollView>
    );
  }

  handleCapture(e) {
    const focusField = TextInputState.currentlyFocusedField();
    const target = e.nativeEvent.target;
    if (focusField != null && target != focusField){
      const inputs = this.props.inputs;
      if (inputs && inputs.indexOf(target) === -1) {
        dismissKeyboard();
      }
    }
  }
}

InputScrollView.propTypes = {
  inputs : React.PropTypes.array,
}

唯一的缺点是我需要收集所有文本输入的节点句柄(由React.findNodeHandle返回)&#34;手动&#34;并将其作为数组传递给组件。

答案 2 :(得分:2)

我用这段代码解决了我的问题

<ScrollView
   keyboardDismissMode='on-drag'
   keyboardShouldPersistTaps={true}
>

答案 3 :(得分:2)

通过查看https://facebook.github.io/react-native/docs/scrollview.html#keyboarddismissmode,我找到了一种方法可以做到这些:

  1. 在TextInput1中输入后,如果单击Input2,键盘将保持不变。
  2. 如果您点击某处为空,键盘将自动消失。
  3. 代码如下:

    <ScrollView
      keyboardDismissMode="none"
      keyboardShouldPersistTaps="handled"
    >
      {content}
    </ScrollView>
    

答案 4 :(得分:0)

我已更新上述答案,因为不推荐使用keyboardShouldPersistTaps = {true},现在使用了KeyboardShouldPersistTaps ='always'

export class InputScrollView extends React.Component {

  constructor(props, ctx) {
      super(props, ctx);
      this.handleCapture = this.handleCapture.bind(this);
  }

  render() {
    return (
      <ScrollView keyboardShouldPersistTaps='always' keyboardDismissMode='on-drag'>
        <View onStartShouldSetResponderCapture={this.handleCapture}>
          {this.props.children}
        </View>
      </ScrollView>
    );
  }

  handleCapture(e) {
    const focusField = TextInputState.currentlyFocusedField();
    const target = e.nativeEvent.target;
    if (focusField != null && target != focusField){
      const inputs = this.props.inputs;
      if (inputs && inputs.indexOf(target) === -1) {
        dismissKeyboard();
      }
    }
  }
}

InputScrollView.propTypes = {
  inputs : React.PropTypes.array,
}

答案 5 :(得分:0)

在新的本机版本中,您可以像下面这样保留on scrollview click事件:

<ScrollView
      keyboardShouldPersistTaps='always'
      keyboardDismissMode={'interactive'}></ScrollView>

主要技巧是keyboardShouldPersistTaps='always'