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

React Native中TouchableHighlight点击后背景颜色切换失效求助

问题分析与解决方案

你的问题核心在于所有列表项共用了同一个pressed状态,而且错误地使用了onShowUnderlay/onHideUnderlay来控制持久选中状态——这两个回调只是在按下/松开组件时触发临时状态,松开后就会重置,无法实现点击后保持颜色的效果。另外,单个布尔值无法区分多个列表项的选中状态,导致所有项会同时变化。

下面是修复后的完整代码,我做了针对性的优化,同时保留了你原本的需求逻辑:

import React, { Component } from 'react';
import { StyleSheet, Text, StatusBar , TouchableOpacity, View, FlatList, ActivityIndicator, TouchableHighlight, PropTypes, Image, Alert } from 'react-native';
import Logo from '../components/Logo';
import Form from '../components/Front';
import {Actions} from 'react-native-router-flux';

export default class Login extends Component<{}> {
  constructor() {
    super();
    this.state = {
      dataSource: [],
      selectedNumbers: [] // 存储选中的数字ID,替代原有的单个pressed状态
    };
  }

  izijackpotconfirm() {
    Actions.izijackpotconfirm()
  }

  componentDidMount() {
    let items = Array.apply(null, Array(25)).map((v, i) => {
      return { id: i+1 };
    });
    this.setState({
      dataSource: items,
    });
  }

  static navigationOptions = {
    title: "Izi Jackpot",
    headerStyle: {
      backgroundColor: "#354247"
    },
    headerTintColor: "#fff",
    headerTitleStyle: {
      fontWeight: "bold"
    }
  };

  // 切换单个数字的选中状态,同时限制最多选5个
  toggleNumberSelection = (numberId) => {
    this.setState(prevState => {
      let newSelected = [...prevState.selectedNumbers];
      if (newSelected.includes(numberId)) {
        // 已选中则移除
        newSelected = newSelected.filter(id => id !== numberId);
      } else {
        // 未选中则添加,同时判断是否超过5个上限
        if (newSelected.length < 5) {
          newSelected.push(numberId);
        } else {
          Alert.alert("提示", "最多只能选择5个数字");
        }
      }
      return { selectedNumbers: newSelected };
    });
  }

  render() {
    return(
      <View style={styles.container}>
        <View style={styles.middlecontainer}>
          <Text style={styles.logoText}>Please Select 5 Numbers and Submit</Text>
        </View>
        <FlatList
          data={this.state.dataSource}
          renderItem={({ item }) => {
            // 判断当前数字是否被选中
            const isSelected = this.state.selectedNumbers.includes(item.id);
            return (
              <View style={{ flex: 1, flexDirection: 'column', margin: 1 }}>
                <TouchableHighlight
                  onPress={() => this.toggleNumberSelection(item.id)}
                  style={[
                    styles.iziPizi,
                    isSelected ? styles.iziPiziPress : {} // 根据选中状态切换样式
                  ]}
                  underlayColor={'gray'} // 保留按下时的临时高亮反馈
                >
                  <Text style={styles.buttonText}>{ item.id}</Text>
                </TouchableHighlight>
              </View>
            )
          }}
          numColumns={5}
          keyExtractor={(item, index) => index.toString()}
        />
        <View style={styles.middlecontainer}>
          <TouchableOpacity 
            style={styles.button} 
            onPress={this.izijackpotconfirm}
            disabled={this.state.selectedNumbers.length !==5} // 未选满5个时禁用提交按钮
          >
            <Text style={styles.buttonText}>Submit</Text>
          </TouchableOpacity>
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container : {
    backgroundColor:'#6F9000',
    justifyContent: 'center',
    flex: 1,
    paddingTop: 30,
  },
  middlecontainer: {
    textAlign: 'center',
    alignItems: 'center',
    justifyContent :'center',
    flex:1
  },
  signupTextCont : {
    flexGrow: 1,
    alignItems:'flex-end',
    justifyContent :'center',
    paddingVertical:16,
    flexDirection:'row'
  },
  signupText: {
    color:'rgba(255,255,255,0.6)',
    fontSize:16
  },
  signupButton: {
    color:'#ffffff',
    fontSize:16,
    fontWeight:'500'
  },
  iziPizi: {
    width: 55,
    padding: 15,
    margin: 5,
    borderRadius: 80,
    borderWidth: 2,
    borderColor: '#FFFFFF',
    flex:1,
    backgroundColor: 'transparent' // 默认透明背景
  },
  iziPiziPress: {
    width: 55,
    padding: 15,
    margin: 5,
    backgroundColor:'#1c313a',
    borderRadius: 80,
    borderWidth: 2,
    borderColor: '#FFFFFF',
    flex:1
  },
  button: {
    width:300,
    backgroundColor:'#1c313a',
    borderRadius: 25,
    marginVertical: 10,
    paddingVertical: 13,
    opacity: 0.8 // 禁用时降低透明度提示用户
  },
  buttonText: {
    fontSize:16,
    fontWeight:'500',
    color:'#ffffff',
    textAlign:'center'
  },
  logoText : {
    color:'#FFFFFF',
    fontSize: 16,
    fontWeight: '500',
    alignItems: 'center',
    justifyContent:'center',
  },
  imageThumbnail: {
    justifyContent: 'center',
    alignItems: 'center',
    height: 100,
  },
});

关键修改说明

  1. 状态管理优化:用selectedNumbers数组替代单个pressed布尔值,每个数字的选中状态独立存储,彻底解决了所有项同时变化的问题。
  2. 选中逻辑调整:通过toggleNumberSelection方法处理点击事件,实现选中/取消选中的切换,同时添加了最多选5个的限制(符合需求里的"Select 5 Numbers"提示)。
  3. 样式应用修正:渲染每个项时,根据isSelected判断是否应用选中样式,实现点击后持久保持背景色的效果。
  4. 用户体验提升:添加了提交按钮的禁用逻辑,未选满5个时按钮不可点击,同时给出弹窗提示,避免无效操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:03:18