React Native中实现TouchableOpacity按钮点击切换背景颜色的方案咨询及代码示例请求
实现点击切换圆形按钮背景色的解决方案
你已经搭好了基础的状态结构,现在只需要添加点击事件处理逻辑,就能动态更新isCheck状态,实现按钮点击变蓝、未点击透明的效果。下面是具体的修改步骤和完整代码:
核心修改思路
- 添加状态更新函数:在父组件中创建一个处理点击的函数,用来切换对应选项的
isCheck状态 - 传递回调到子组件:把这个更新函数作为props传给
renderItem,让子组件能触发状态变更 - 绑定点击事件:给每个圆形
TouchableOpacity添加onPress事件,调用传递过来的更新函数
修改后的完整代码
import React, {useState} from 'react'; import { StyleSheet, Text, View, Button, FlatList, Dimensions, TouchableOpacity, Image, } from 'react-native'; import Modal from 'react-native-modal'; const {width: screenWidth} = Dimensions.get('screen'); // screen width Multiply by 0.8 const Footer = () => { return ( <View> <Text style={{color: '#fff', fontSize: 20}}>Reviews</Text> <View style={{flexDirection: 'row', alignItems: 'center', marginTop: 20}}> <Image source={require('../assets/five-stars.png')} style={{width: 90, height: 18}} /> <Text style={{marginLeft: 10}}>& Up</Text> </View> <View style={{flexDirection: 'row', marginTop: 30}}> <TouchableOpacity style={{ backgroundColor: '#525252', width: 200, paddingTop: 20, paddingBottom: 20, alignItems: 'center', borderTopLeftRadius: 22, }}> <Text>Reset</Text> </TouchableOpacity> <TouchableOpacity style={{ backgroundColor: '#00ACED', width: 200, alignItems: 'center', paddingTop: 20, paddingBottom: 20, borderTopRightRadius: 23, }}> <Text>Apply</Text> </TouchableOpacity> </View> </View> ); }; // 修改renderItem,接收handlePress回调 const renderItem = ({item: {title, data, key}, handlePress}) => ( <View> <Text style={styles.headingText}>{title}</Text> <View style={styles.item}> {data.map(el => ( <TouchableOpacity key={el.key} style={[ { backgroundColor: el.isCheck ? '#00ACED' : 'transparent', padding: 20, borderColor: '#185268', borderWidth: 2, borderRadius: 40, marginBottom: 10, marginRight: 10, }, ]} // 添加点击事件,传递父项和子项的key用于定位 onPress={() => handlePress(key, el.key)} > <Text style={styles.btnText}>{el.name}</Text> </TouchableOpacity> ))} </View> </View> ); const SandboxScreen = () => { const [isModalVisible, setModalVisible] = useState(false); const [data, setData] = useState([ { key: 'id-1', title: 'Workshop Category', data: [ {name: 'BodyShops', isCheck: false, key: 'id-5'}, {name: 'Electric Cars', isCheck: true, key: 'id-6'}, {name: 'Performance Shops', isCheck: false, key: 'id-7'}, ], }, { key: 'id-2', title: 'Vehicle Category', data: [ {name: 'Cars', isCheck: false, key: 'id-8'}, {name: 'Trucks', isCheck: true, key: 'id-9'}, {name: 'Motorbikes', isCheck: false, key: 'id-10'}, ], }, { key: 'id-3', title: 'Services', data: [ {name: 'Accident Repair', isCheck: false, key: 'id-11'}, {name: 'AC System Diagnosis', isCheck: false, key: 'id-12'}, {name: 'Car Polishing / Detailing', isCheck: false, key: 'id-13'}, {name: 'Electric / Hybrid System Repair', isCheck: true, key: 'id-14'}, {name: 'General Mechanical Work', isCheck: true, key: 'id-15'}, ], }, { key: 'id-4', title: 'Brands', data: [ {name: 'FORD', isCheck: false, key: 'id-16'}, {name: 'BMW', isCheck: false, key: 'id-17'}, {name: 'BMW', isCheck: false, key: 'id-18'}, {name: 'AUDI', isCheck: false, key: 'id-19'}, {name: 'JAGUAR', isCheck: false, key: 'id-20'}, {name: 'FERRARI', isCheck: true, key: 'id-21'}, {name: 'LAMBORGHINI', isCheck: false, key: 'id-22'}, ], }, ]); const toggleModal = () => { setModalVisible(prevState => !prevState); }; // 核心:处理按钮点击,切换对应项的isCheck状态 const handleItemPress = (parentKey, itemKey) => { setData(prevData => { return prevData.map(parentItem => { // 定位到对应的父分类 if (parentItem.key === parentKey) { return { ...parentItem, // 更新子项的选中状态 data: parentItem.data.map(item => { if (item.key === itemKey) { return {...item, isCheck: !item.isCheck}; } return item; }) }; } return parentItem; }); }); }; return ( <View style={[ { flex: 1, backgroundColor: '#252525', }, ]}> <View style={styles.container}> <FlatList data={data} // 将handleItemPress传递给renderItem组件 renderItem={(props) => renderItem({...props, handlePress: handleItemPress})} keyExtractor={item => item.key} ListFooterComponent={Footer} /> </View> {/* <Button title="Show modal" onPress={toggleModal} /> <Modal isVisible={isModalVisible} animationIn="slideInRight" animationOut="slideOutRight" animationInTiming={500} animationOutTiming={500} hasBackdrop={true} backdropColor="#252525" backdropOpacity={0.8} backdropTransitionInTiming={500} backdropTransitionOutTiming={500} onBackdropPress={() => setModalVisible(false)} style={{alignItems: 'flex-end', margin: 0}}> <View style={{ backgroundColor: 'white', flex: 1, paddingTop: 50, width: screenWidth * 0.7, }}> <View style={styles.container}> <FlatList data={DATA} renderItem={renderItem} keyExtractor={item => item.id} /> </View> </View> </Modal> */} </View> ); }; export default SandboxScreen; const styles = StyleSheet.create({ container: {}, button: { backgroundColor: 'green', padding: 13, }, headingText: { color: '#fff', fontSize: 20, marginBottom: 20, }, item: { flexDirection: 'row', flexWrap: 'wrap', marginBottom: 40, }, btnText: { // 优化:点击后文字变白色,和蓝色背景更适配 color: '#fff', }, });
关键修改说明
- 不可变状态更新:使用展开运算符
...复制原数组/对象,避免直接修改状态,符合React的状态更新规范 - 精准定位修改项:通过父项
key和子项key双重定位,确保只修改被点击的按钮状态 - 视觉优化:新增
btnText样式,让按钮文字在蓝色背景下更清晰可读
现在点击每个圆形按钮时,就会切换它的背景色:点击时变为蓝色,再次点击恢复透明,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Abdul Basit
相关产品推荐
相关产品推荐

