You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ScrollView内嵌TouchableOpacity首次点击无响应如何实现单次触发?

我已经查阅过该主题的相关同类问题,请不要急于关闭此问题。

我开发了一个搜索页面,输入搜索词后会拉取对应的结果列表。拉取完成后我希望点击任意一条结果即可跳转到该对象的详情页,但目前首次点击始终无法被检测到,只有第二次点击才能生效。我的组件代码如下:

return (
  <View>
    <TextInput
      value={query}
      placeholder="Type Here..."
      onChangeText={(search) => setQuery(search)}
    />
    {fetching ? (
      <Spinner
        visible={fetching}
        textContent={'Fetching data...'}
        textStyle={{ fontSize: 14 }}
      />
    ) : null}
    {items ? (
      <ScrollView keyboardShouldPersistTaps={true}>
        <FlatList
          numColumns={1}
          horizontal={false}
          data={items}
          keyExtractor={(item) => item.id}
          renderItem={({ item }) => (
            <TouchableOpacity
              onPress={() =>
                navigation.navigate('Item Details', { id: item.id })
              }>
              <ItemDisplay item={item} keyboardShouldPersistTaps="always" />
            </TouchableOpacity>
          )}
        />
      </ScrollView>
    ) : null}
  </View>
);

我的ItemDisplay组件仅用于展示一行包含条目图片和条目ID的内容,无特殊逻辑。

按照同类问题的解决方案建议,我已经给<ScrollView keyboardShouldPersistTaps={true}>设置了对应属性,也给<ItemDisplay item={item} keyboardShouldPersistTaps="always" />传入了对应配置,但问题仍然没有解决,我还是需要点击两次才能触发跳转。请问有什么方法可以修复这个问题?我是在安卓端进行测试的,供参考。

我也尝试过给ScrollView配置keyboardDismissMode="on-drag" keyboardShouldPersistTaps={"always"},同样没有生效。


问题原因

你的问题是嵌套滚动组件导致的键盘事件冲突:FlatList本身自带滚动能力,你额外在外层套了ScrollView,两个滚动组件的键盘焦点处理逻辑互相冲突,导致你设置的keyboardShouldPersistTaps没有真正生效,第一次点击被系统用来回收键盘焦点,第二次点击才会触发TouchableOpacity的事件。

修复步骤

  1. 移除冗余的外层ScrollView,将keyboardShouldPersistTaps属性直接配置在FlatList上,安卓端推荐使用handled值,兼容性比always更好
  2. 给TextInput添加blurOnSubmit={true}属性,输入完成后自动收起键盘,避免焦点残留
  3. 不需要给普通展示组件ItemDisplay传keyboardShouldPersistTaps属性,该属性仅对滚动类组件生效,传给普通组件没有任何作用
  4. 如果调整后仍有问题,可以将TouchableOpacity的onPress替换为onPressIn,优先响应按下事件,避开焦点抢占逻辑

修改后参考代码

return (
  <View>
    <TextInput
      value={query}
      placeholder="Type Here..."
      onChangeText={(search) => setQuery(search)}
      blurOnSubmit={true}
    />
    {fetching ? (
      <Spinner
        visible={fetching}
        textContent={'Fetching data...'}
        textStyle={{ fontSize: 14 }}
      />
    ) : null}
    {items ? (
      <FlatList
        numColumns={1}
        horizontal={false}
        data={items}
        keyExtractor={(item) => item.id}
        keyboardShouldPersistTaps="handled"
        renderItem={({ item }) => (
          <TouchableOpacity
            onPress={() =>
              navigation.navigate('Item Details', { id: item.id })
            }>
            <ItemDisplay item={item} />
          </TouchableOpacity>
        )}
      />
    ) : null}
  </View>
);

如果你的页面确实需要外层滚动容器包裹多个模块,保留ScrollView的同时需要将两个滚动组件的keyboardShouldPersistTaps都设置为handled即可。


内容的提问来源于stack exchange,提问作者newbie coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 18:45:04