React Native:ScrollView 内的 TouchableOpacity onPress 问题
React Native: TouchableOpacity onPress problems inside a ScrollView
我是 运行 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 也确实发生了这种情况。
在您的 ScrollView
上设置 keyboardShouldPersistTaps={true}
。
此处重复答案:
更新: 正如侯赛因在他的回答中所写,true|false
在较新的版本中已被弃用,取而代之的是 always|never|handled
。
将 keyboardShouldPersistTaps='always'
设置为您的 ScrollView
道具。
React Native 文档:
'never'(默认值),当键盘弹起时在聚焦文本输入的外部点击会关闭键盘。发生这种情况时,children 将不会收到点击。
'always',键盘不会自动关闭,滚动视图不会捕获点击,但滚动视图的 children 可以捕获点击.
'handled',当点击由 children 处理(或由祖先捕获)时,键盘不会自动关闭。
false,已弃用,请改用 'never'。
true,已弃用,请改用 'always'。
就我而言,当我切换到 alignItems:'center'[=14= 时,我使用的是 alignItems:'baseline', ],它开始顺利工作。不知道为什么
我是 运行 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 也确实发生了这种情况。
在您的 ScrollView
上设置 keyboardShouldPersistTaps={true}
。
此处重复答案:
更新: 正如侯赛因在他的回答中所写,true|false
在较新的版本中已被弃用,取而代之的是 always|never|handled
。
将 keyboardShouldPersistTaps='always'
设置为您的 ScrollView
道具。
React Native 文档:
'never'(默认值),当键盘弹起时在聚焦文本输入的外部点击会关闭键盘。发生这种情况时,children 将不会收到点击。
'always',键盘不会自动关闭,滚动视图不会捕获点击,但滚动视图的 children 可以捕获点击.
'handled',当点击由 children 处理(或由祖先捕获)时,键盘不会自动关闭。
false,已弃用,请改用 'never'。
true,已弃用,请改用 'always'。
就我而言,当我切换到 alignItems:'center'[=14= 时,我使用的是 alignItems:'baseline', ],它开始顺利工作。不知道为什么