React Native:ScrollView内TouchableOpacity onPress问题

18

我正在运行react native 0.24.1,并且在将<TouchableOpacity>组件放置在<ScrollView>内时遇到了问题。

它的onPress事件可以正常触发,但有一种特殊情况下不会触发。 如果与<TouchableOpacity>组件一起使用一个<TextInput>,并且当前焦点在<TextInput>框上,那么您可能会单击<TouchableOpacity>,但是它的 onPress 事件将不会被触发。

至少第一次这样做。一旦焦点不再在<TextInput>上,您现在可以按下<TouchableOpacity>组件,它的onPress事件就会正常触发。

请注意,如果<TouchableOpacity>组件放置在<View>而不是<ScrollView>中,则一切正常,上述问题不适用。

以下是演示问题的一些代码:

const React = require('react-native');
const {
  Component,
  Dimensions,
  View,
  ScrollView,
  Text,
  TextInput,
  TouchableOpacity,
} = React;


// ----------------------------------------------------------------------------
class TouchableOpacityTest extends Component {
  constructor(props, context) {
    super(props, context);
    this.state = {count_onPress:0,count_onPressIn:0,count_onPressOut:0,count_onLongPress:0};
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  onPressEvent(what,e) {
    console.log('what:',what);
    let newState = {};
    newState['count_'+what] = ++this.state['count_'+what];
    this.setState(newState);
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  render() {
    let touchableProps = {
      onPress: this.onPressEvent.bind(this,'onPress'),
      onPressIn: this.onPressEvent.bind(this,'onPressIn'),
      onPressOut: this.onPressEvent.bind(this,'onPressOut'),
      onLongPress: this.onPressEvent.bind(this,'onLongPress'),
    }

    return (
      <View style={{flex:1,flexDirection:'column',justifyContent:'flex-start',alignItems:'center',backgroundColor:'blue'}} >
        <ScrollView style={{width:Dimensions.get('window').width*0.9,backgroundColor:'red'}}>
          <TextInput style={{backgroundColor:'rgb(200,200,200)',marginTop:14}}
            placeholder="Focus on me,hide keyboard,and click on text below"
            autoCorrect={false}
          />
          <TouchableOpacity {...touchableProps} >
            <Text style={{fontSize:20,backgroundColor:'pink',marginTop:14}}>
              Click on me!{"\n"}
              onPress:{this.state.count_onPress}{"\n"}
              onPressIn:{this.state.count_onPressIn}{"\n"}
              onPressOut:{this.state.count_onPressOut}{"\n"}
              onLongPress:{this.state.count_onLongPress}{"\n"}
            </Text>
          </TouchableOpacity>
        </ScrollView>
      </View>
    );
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
// ----------------------------------------------------------------------------
AppRegistry.registerComponent('react_native_app1', () => TouchableOpacityTest);
您可以将上述代码中的<ScrollView>替换为<View>组件,您会发现onPress事件每次都会触发,即使焦点在<TextView>上。

注:我正在使用Android。 我不知道这是否也会发生在iOS上。

注2:根据Aakash Sigdel的说法,这确实也会在iOS上发生。


尝试使用其中之一的keyboardDismissMode={'none', 'ondrag','interactive'}。 - Mihir
我在iOS上进行了检查,并确认这种情况也发生在iOS上。 - Aakash Sigdel
我曾经遇到过类似的问题,就是在 ScrollView 旁边放了一个 TouchableOpacity,但是即使移除了 ScrollView,问题仍然没有解决。相反,我将按钮的大小增加到最小推荐尺寸 44x44,之后按钮就能识别所有的点击事件了。 - Adam Loving
3个回答

21

在你的ScrollView上设置keyboardShouldPersistTaps={true}

类似答案请参考:https://dev59.com/LlsX5IYBdhLWcg3wDb6L#34290788

更新:如Hossein在他的答案中所写,true|false已经在较新版本中被弃用,取而代之的是always|never|handled


1
谢谢你的帮助,伙计 :) - Hanish Sharma

11

keyboardShouldPersistTaps='always'设置为您的ScrollView属性。

React Native文档:

'never'(默认值),当键盘弹出时,点击文本输入框外部会关闭键盘。在此情况下,子组件不会接收到任何触摸事件。

'always',键盘不会自动关闭,且滚动视图不会捕捉触摸事件,但滚动视图的子组件可以捕捉到事件。

'handled',当触摸事件被子组件处理或由祖先元素捕捉到时,键盘不会自动关闭。

false,已过时,请改用'never'。

true,已过时,请改用'always'。


1
如果有帮助的话,我遇到了同样的问题,只是在iPhone X上发生了,而在iPhone 6 Plus上没有发生。 - FurkanO

0
在我的情况下,我使用了alignItems:'baseline',当我切换到alignItems:'center'时,它开始平稳地工作了。不知道为什么。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接