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

React Native中实现TouchableOpacity按钮点击切换背景颜色的方案咨询及代码示例请求

实现点击切换圆形按钮背景色的解决方案

你已经搭好了基础的状态结构,现在只需要添加点击事件处理逻辑,就能动态更新isCheck状态,实现按钮点击变蓝、未点击透明的效果。下面是具体的修改步骤和完整代码:

核心修改思路

  1. 添加状态更新函数:在父组件中创建一个处理点击的函数,用来切换对应选项的isCheck状态
  2. 传递回调到子组件:把这个更新函数作为props传给renderItem,让子组件能触发状态变更
  3. 绑定点击事件:给每个圆形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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 11:07:48