react-native-calendars库Agenda组件点击修改单个条目颜色实现问题
问题根因
你之前所有条目同时高亮的核心原因是没有为单个用药条目维护独立的完成状态,使用全局状态控制样式会导致所有条目同步变更。
具体修改方案
- 将Agenda的条目数据从组件属性移入state,给每个条目增加唯一id和
completed字段标记是否已服用 - 新增条目点击状态切换方法,点击时仅修改对应条目的completed状态
- 改造renderItem逻辑,根据条目自身的completed属性动态绑定样式
- 新增已完成条目的自定义样式
修改后完整代码
组件逻辑代码
import React from 'react'; import { View, Text, Switch, TouchableOpacity, StyleSheet, Alert } from 'react-native'; import { Agenda } from 'react-native-calendars'; export default class App extends React.Component { state = { toggled: false, // 条目数据移入state,每个条目新增唯一id和完成状态标记 items: { '2012-05-22': [ {id: '1', name: '9 AM - 1粒200mg对乙酰氨基酚', completed: false} ], '2012-05-23': [ {id: '2', name: '9 AM - 1粒200mg对乙酰氨基酚', completed: false}, {id: '3', name: '10 AM - 1粒500mg镁片', completed: false} ], '2012-05-24': [ {id: '4', name: '9 AM - 1粒200mg对乙酰氨基酚', completed: false} ], '2012-05-25': [ {id: '5', name: '9 AM - 1粒200mg对乙酰氨基酚', completed: false}, {id: '6', name: '10 AM - 1粒500mg镁片', completed: false} ] }, selected: '2012-05-22' } toggleSwitch = (value) => { this.setState({toggled: value}) } // 新增条目状态切换方法,仅修改当前点击条目的状态 toggleItemComplete = (date, item) => { const updatedItems = {...this.state.items}; const targetDateItems = updatedItems[date]; const targetItemIndex = targetDateItems.findIndex(i => i.id === item.id); if (targetItemIndex > -1) { targetDateItems[targetItemIndex].completed = !targetDateItems[targetItemIndex].completed; this.setState({ items: updatedItems }); } } render() { return ( <View style={styles.background}> <View style={styles.medicationHeaderContainer}> <Text style={styles.medicationHeader}>用药管理</Text> </View> <View style={styles.reminderAlertContainer}> <Text style={styles.reminderAlertText}>用药提醒</Text> <Switch onValueChange={this.toggleSwitch} value={this.state.toggled} style={styles.reminderAlertSwitch}/> </View> <Agenda items={this.state.items} selected={this.state.selected} renderItem={(item) => this.renderItem(item, this.state.selected)} > </Agenda> </View> ); } // 改造渲染逻辑,动态绑定样式 renderItem(item, currentDate) { return ( <TouchableOpacity style={[styles.item, item.completed ? styles.itemCompleted : {}]} onPress={() => this.toggleItemComplete(currentDate, item)} > <View> <Text>{item.name}</Text> </View> </TouchableOpacity> ); } }
样式表代码
const styles = StyleSheet.create({ background: { flex: 1, backgroundColor: "#fff" }, medicationHeaderContainer: { marginTop: 40, height: "10%", backgroundColor: "#fff" }, medicationHeader: { fontSize: 40, bottom: -30, fontWeight: "bold", marginLeft: 15 }, reminderAlertContainer: { marginTop: 5, height: '7%', width: '95%', backgroundColor: "#85C1E9", borderRadius: 10, marginLeft: 10 }, reminderAlertText: { fontSize: 30, bottom: -10, marginLeft: 15, color: '#fff', fontWeight: "bold", }, reminderAlertSwitch: { bottom: 20, marginLeft: 320 }, item: { backgroundColor: 'white', flex: 1, borderRadius: 5, padding: 10, marginRight: 10, marginTop: 17 }, // 新增已完成条目样式,可自行调整颜色 itemCompleted: { backgroundColor: '#d4edda' }, emptyDate: { height: 15, flex: 1, paddingTop: 30 } });
如果需要重启App后仍保留服用标记,可以将state中的items数据持久化存储到AsyncStorage中。
内容的提问来源于stack exchange,提问作者Ehsaas
相关产品推荐
相关产品推荐

