简体   繁体   English

React Native:ScrollView 中的 TouchableOpacity onPress 问题

[英]React Native: TouchableOpacity onPress problems inside a ScrollView

I am running react native 0.24.1 and I am experiencing an issue with the <TouchableOpacity> component when it is placed inside an <ScrollView> .我正在运行 react native 0.24.1,当<TouchableOpacity>组件放置在<ScrollView>时,我遇到了问题。

Its onPress events fire fine but there is a special case when they do not.它的onPress事件触发得很好,但有一个特殊情况,当他们没有触发时。 If along with the <TouchableOpacity> component you have a <TextInput> , and the current focus is on the <TextInput> box, then you may click on the <TouchableOpacity> and you will see its onPress event WILL NOT be fired.如果与<TouchableOpacity>组件一起有一个<TextInput> ,并且当前焦点位于<TextInput>框上,那么您可以单击<TouchableOpacity>并且您将看到它的onPress事件不会被触发。

At least the first time you do it.至少你第一次这样做。 Once the focus is NOT on the <TextInput> anymore, you can now press on the <TouchableOpacity> component and its onPress event will fire just fine.一旦焦点不再位于<TextInput> ,您现在可以按下<TouchableOpacity>组件,它的onPress事件将正常触发。

Note that if the <TouchableOpacity> component is placed inside a <View> instead of an <ScrollView> everything works as expected and the above issue does not apply.请注意,如果<TouchableOpacity>组件放置在<View>而不是<ScrollView>一切都按预期工作,并且上述问题不适用。

Here is some code to demonstrate the problem:下面是一些代码来演示这个问题:

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

You may replace the <ScrollView> with a <View> component on the above code and you will see that onPress event fires every time, even when the focus is on the <TextView>您可以在上面的代码中将<ScrollView>替换为<View>组件,您将看到每次都会触发onPress事件,即使焦点位于<TextView>

NOTE: I am working on Android.注意:我在 Android 上工作。 I have no idea if this happens also on iOS.我不知道这是否也发生在 iOS 上。

NOTE 2: According to Aakash Sigdel, this is indeed happening on iOS too.注意 2:根据 Aakash Sigdel 的说法,这也确实发生在 iOS 上。

Set keyboardShouldPersistTaps={true} on your ScrollView .ScrollView上设置keyboardShouldPersistTaps={true}

Duplicate answer here: https://stackoverflow.com/a/34290788/29493这里有重复的答案: https : //stackoverflow.com/a/34290788/29493

UPDATE: As Hossein writes in his answer, true|false has been deprecated in newer versions in favor of always|never|handled .更新:正如侯赛因在他的回答中所写的那样, true|false在较新的版本中已被弃用,而支持always|never|handled

Set keyboardShouldPersistTaps='always' to your ScrollView props.keyboardShouldPersistTaps='always'为您的ScrollView道具。

React Native Documentation:反应本机文档:

'never' (the default), tapping outside of the focused text input when the keyboard is up dismisses the keyboard. “从不” (默认值),当键盘向上时在焦点文本输入之外轻敲会关闭键盘。 When this happens, children won't receive the tap.发生这种情况时,儿童将不会收到水龙头。

'always' , the keyboard will not dismiss automatically, and the scroll view will not catch taps, but children of the scroll view can catch taps. 'always' ,键盘不会自动关闭,滚动视图不会捕捉点击,但滚动视图的孩子可以捕捉点击。

'handled' , the keyboard will not dismiss automatically when the tap was handled by a children, (or captured by an ancestor). 'handled' ,当点击被孩子处理(或被祖先捕获)时,键盘不会自动关闭。

false , deprecated, use 'never' instead. false ,已弃用,请改用“从不”。

true , deprecated, use 'always' instead. true ,已弃用,请改用“始终”。

In my case, I was using alignItems:'baseline', when I switched to alignItems:'center' , it started working smoothly.就我而言,我使用的是alignItems:'baseline',当我切换到alignItems:'center' 时,它开始顺利工作。 Don't know why不知道为什么

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM