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

React Native中TouchableOpacity的onPress在子组件上失效求助

问题原因

你遇到的问题是因为react-native-paper的TextInput是自带交互的组件,它会拦截触摸事件,导致外层的TouchableOpacity只能接收到组件边缘(Animated.View的空白区域)的点击,点击TextInput本身时事件被组件消耗,外层onPress无法触发。

修复方案

方案1:给SearchComponent传递点击回调,在TextInput上触发

修改SearchComponent.js,接收父组件的点击回调并绑定到TextInput的触摸事件:

import React, { useEffect, useState } from 'react'
import { Animated } from 'react-native'
import { TextInput } from 'react-native-paper';

export default function SearchComponent({ expanded = false, onPress }) {

    const [search, setSearch] = useState('')
    const [bottom] = useState(new Animated.Value(0))

    useEffect(() => {
        Animated.timing(bottom, {
            toValue: !expanded ? 80 : 10,
            duration: 150,
            useNativeDriver: false
        }).start();
    }, [expanded, bottom]);


    return (
        <Animated.View style={{ bottom, backgroundColor: 'red', borderWidth: 3, borderColor: 'red' }}>
            <TextInput 
                placeholder='Search' 
                defaultValue={search} 
                onChangeText={e => setSearch(e)} 
                style={{
                    backgroundColor: 'white', 
                    borderRadius: 20
                }}
                // 触发父组件的点击逻辑
                onTouchEnd={onPress}
            />
        </Animated.View>
    )
}

修改App.js,给SearchComponent传递onPress参数:

<View style={styles.searchContainer} >
    <TouchableOpacity
        onPress={() => setExpanded(!expanded)}>
        <SearchComponent expanded={expanded} onPress={() => setExpanded(!expanded)} />
    </TouchableOpacity>
</View>

方案2:将TouchableOpacity移到SearchComponent内部

把触摸容器放到组件内部,确保整个搜索区域都能响应点击,同时保留TextInput的输入功能:

import React, { useEffect, useState } from 'react'
import { Animated, TouchableOpacity } from 'react-native'
import { TextInput } from 'react-native-paper';

export default function SearchComponent({ expanded = false, onPress }) {

    const [search, setSearch] = useState('')
    const [bottom] = useState(new Animated.Value(0))

    useEffect(() => {
        Animated.timing(bottom, {
            toValue: !expanded ? 80 : 10,
            duration: 150,
            useNativeDriver: false
        }).start();
    }, [expanded, bottom]);


    return (
        <Animated.View style={{ bottom, backgroundColor: 'red', borderWidth: 3, borderColor: 'red' }}>
            <TouchableOpacity 
                onPress={onPress}
                style={{flex: 1}}
                activeOpacity={1} // 避免触摸时改变TextInput透明度
            >
                <TextInput 
                    placeholder='Search' 
                    defaultValue={search} 
                    onChangeText={e => setSearch(e)} 
                    style={{
                        backgroundColor: 'white', 
                        borderRadius: 20
                    }}
                />
            </TouchableOpacity>
        </Animated.View>
    )
}

此时App.js可以简化,移除外层的TouchableOpacity:

<View style={styles.searchContainer} >
    <SearchComponent expanded={expanded} onPress={() => setExpanded(!expanded)} />
</View>

额外优化(可选)

如果希望点击TextInput时既触发展开/收起,又能自动聚焦输入,可以给TextInput添加ref并手动聚焦:

// 在SearchComponent中添加ref
const inputRef = useRef(null);

// 修改onTouchEnd逻辑
onTouchEnd={() => {
  onPress();
  inputRef.current?.focus();
}}

// 给TextInput绑定ref
<TextInput ref={inputRef} ... />

内容的提问来源于stack exchange,提问作者noor.soreti

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:00:21