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

Я запускаю реакцию 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: По словам Акаша Сигделя, это действительно происходит и на iOS.

Ответ 1

Установите keyboardShouldPersistTaps={true} на ScrollView.

Повторяющийся ответ здесь: fooobar.com/questions/557226/...

ОБНОВЛЕНИЕ: Как пишет Хоссейн в своем ответе, true|false устарел в новых версиях в пользу always|never|handled.

Ответ 2

Установите keyboardShouldPersistTaps='always' в реквизиты ScrollView.

Реальная документация:

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

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

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

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

true, устаревший, используйте "всегда".