React Native: проблемы TouchableOpacity onPress внутри ScrollView

я запускаю react native 0.24.1, и у меня возникает проблема с <TouchableOpacity> компонент, когда он находится внутри <ScrollView>.

его onPress события срабатывают нормально, но есть особый случай, когда они этого не делают. Если вместе с <TouchableOpacity> компонент у вас есть <TextInput>, и текущий фокус находится на <TextInput> box, затем вы можете нажать на <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 тоже.

2 ответов


Set keyboardShouldPersistTaps={true} на ScrollView.

дубликат ответа здесь:https://stackoverflow.com/a/34290788/29493

обновление: как пишет Хоссейн в своем ответе,true|false устарел в более новых версиях в пользу always|never|handled.


Set keyboardShouldPersistTaps='always' на ScrollView реквизит.

React Родная Документация:

'никогда' (по умолчанию), нажав вне сфокусированного ввода текста, когда клавиатура вверх отклоняет клавиатуру. Когда это произойдет, дети не получат кран.

'всегда' клавиатура автоматически не увольнять, а прокрутки не проймешь краны, но дети прокрутки можно поймать краны.

'обрабатывается', клавиатура не будет автоматически отклоняться, когда кран был обработан детьми (или захвачен предком).

false, устарел, вместо этого используйте "никогда".

правда, не 'всегда' вместо этого.