import { Ionicons } from '@expo/vector-icons'; import React, { useEffect, useState } from 'react'; import { Dimensions, Keyboard, KeyboardAvoidingView, Modal, Platform, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View, } from 'react-native'; // 食物数据类型定义 export interface FoodItem { id: string; name: string; emoji: string; calories: number; unit: string; // 单位,如 "100克" } // 营养信息接口 interface NutritionInfo { protein: number; // 蛋白质(克) fat: number; // 脂肪(克) carbs: number; // 碳水化合物(克) } // 单位选项 const UNIT_OPTIONS = [ { id: 'gram', name: '克', ratio: 1 }, { id: 'small', name: '小份', ratio: 0.8 }, { id: 'medium', name: '中份', ratio: 1.2 }, { id: 'large', name: '大份', ratio: 1.5 }, ]; // 食物详情弹窗属性 export interface FoodDetailModalProps { visible: boolean; food: FoodItem | null; onClose: () => void; onSave: (food: FoodItem, amount: number, unit: string) => void; } // 模拟营养数据 const getNutritionInfo = (foodId: string): NutritionInfo => { const nutritionData: Record = { '5': { protein: 0.8, fat: 0.6, carbs: 14.5 }, // 猕猴桃 '1': { protein: 0.2, fat: 0.0, carbs: 0.1 }, // 咖啡 '2': { protein: 12.8, fat: 11.1, carbs: 0.7 }, // 荷包蛋 '3': { protein: 13.3, fat: 8.8, carbs: 2.8 }, // 鸡蛋 '4': { protein: 1.4, fat: 0.2, carbs: 22.8 }, // 香蕉 '6': { protein: 0.2, fat: 0.2, carbs: 13.8 }, // 苹果 '7': { protein: 0.7, fat: 0.3, carbs: 7.7 }, // 草莓 '8': { protein: 6.6, fat: 4.6, carbs: 22.7 }, // 蛋烧麦 '9': { protein: 2.6, fat: 0.3, carbs: 25.9 }, // 米饭 '10': { protein: 4.0, fat: 1.2, carbs: 22.8 }, // 玉米 }; return nutritionData[foodId] || { protein: 0, fat: 0, carbs: 0 }; }; export function FoodDetailModal({ visible, food, onClose, onSave }: FoodDetailModalProps) { const [amount, setAmount] = useState('100'); const [selectedUnit, setSelectedUnit] = useState(UNIT_OPTIONS[0]); const [isFavorite, setIsFavorite] = useState(false); const [keyboardHeight, setKeyboardHeight] = useState(0); // 键盘监听 useEffect(() => { const keyboardDidShowListener = Keyboard.addListener( Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow', (e) => { console.log('键盘显示,高度:', e.endCoordinates.height); setKeyboardHeight(e.endCoordinates.height); } ); const keyboardDidHideListener = Keyboard.addListener( Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide', () => { console.log('键盘隐藏'); setKeyboardHeight(0); } ); return () => { keyboardDidShowListener?.remove(); keyboardDidHideListener?.remove(); }; }, []); // 重置状态 useEffect(() => { if (visible && food) { console.log('FoodDetailModal: 接收到食物数据:', food); setAmount('100'); setSelectedUnit(UNIT_OPTIONS[0]); setIsFavorite(false); } }, [visible, food]); // 调试信息 console.log('FoodDetailModal render:', { visible, food: food?.name, foodId: food?.id, hasFood: !!food }); if (!food) { console.log('FoodDetailModal: food为空,不渲染内容'); return null; } const nutrition = getNutritionInfo(food.id); const amountNum = parseFloat(amount) || 0; const unitRatio = selectedUnit.ratio; const finalAmount = amountNum * unitRatio; // 计算实际营养值 const actualCalories = Math.round((food.calories * finalAmount) / 100); const actualProtein = ((nutrition.protein * finalAmount) / 100).toFixed(1); const actualFat = ((nutrition.fat * finalAmount) / 100).toFixed(1); const actualCarbs = ((nutrition.carbs * finalAmount) / 100).toFixed(1); const handleSave = () => { onSave(food, finalAmount, selectedUnit.name); onClose(); }; console.log('FoodDetailModal 即将渲染 Modal:', { visible, food: food.name }); return ( 0 && { height: screenHeight - keyboardHeight - 100, // 减去键盘高度和更多安全距离 maxHeight: screenHeight - keyboardHeight - 100, minHeight: Math.min(400, screenHeight * 0.4) // 确保最小高度,但不超过屏幕40% } ]}> 0 ? 20 : 0 // 键盘弹出时增加底部间距 }} scrollEnabled={true} bounces={false} > {/* 头部 */} 我要纠错 {/* 食物信息 */} {food.emoji} {food.name} setIsFavorite(!isFavorite)} style={styles.favoriteButton} > {/* 营养信息 */} 热量 {actualCalories}千卡 蛋白质 {actualProtein}克 脂肪 {actualFat}克 碳水化合物 {actualCarbs}克 {/* 数量输入 */} {/* 单位选择 */} {UNIT_OPTIONS.map((unit) => ( setSelectedUnit(unit)} > {unit.name} ))} {/* 保存按钮 */} 保存 ); } const { width: screenWidth, height: screenHeight } = Dimensions.get('window'); const styles = StyleSheet.create({ overlay: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.5)', justifyContent: 'flex-end', alignItems: 'center', }, keyboardAvoidingView: { width: '100%', justifyContent: 'flex-end', alignItems: 'center', }, modalContainer: { width: screenWidth, backgroundColor: '#FFFFFF', borderRadius: 20, // 四周都设置圆角 // maxHeight: screenHeight * 0.75, // 最大高度为屏幕高度的75% // minHeight: screenHeight * 0.5, // 最小高度为屏幕高度的50% shadowColor: '#000', shadowOffset: { width: 0, height: -5, }, shadowOpacity: 0.25, shadowRadius: 20, elevation: 10, overflow: 'hidden', // 确保内容不会溢出 }, scrollView: { flexGrow: 1, }, header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: screenWidth > 400 ? 24 : 16, // 根据屏幕宽度调整内边距 paddingTop: 16, paddingBottom: 8, }, closeButton: { width: 40, height: 40, borderRadius: 20, backgroundColor: '#F5F5F5', justifyContent: 'center', alignItems: 'center', }, correctButton: { paddingHorizontal: 16, paddingVertical: 8, }, correctButtonText: { fontSize: 16, color: '#4CAF50', fontWeight: '500', }, foodHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: screenWidth > 400 ? 24 : 16, paddingVertical: 12, }, foodInfo: { flexDirection: 'row', alignItems: 'center', flex: 1, }, foodEmoji: { fontSize: 40, marginRight: 12, }, foodName: { fontSize: 20, fontWeight: '600', color: '#333', marginRight: 8, }, favoriteButton: { padding: 8, }, nutritionContainer: { flexDirection: 'row', paddingHorizontal: screenWidth > 400 ? 24 : 16, paddingVertical: 16, justifyContent: 'space-between', }, nutritionItem: { alignItems: 'center', flex: 1, }, nutritionLabel: { fontSize: 14, color: '#666', marginBottom: 8, }, nutritionValue: { fontSize: 16, fontWeight: '600', color: '#333', }, amountContainer: { alignItems: 'center', paddingVertical: 16, }, amountInput: { backgroundColor: '#E8F5E8', borderRadius: 12, paddingHorizontal: 24, paddingVertical: 16, fontSize: 24, fontWeight: '600', color: '#4CAF50', textAlign: 'center', minWidth: 120, }, unitContainer: { flexDirection: 'row', justifyContent: 'center', paddingHorizontal: screenWidth > 400 ? 24 : 16, paddingBottom: 20, gap: screenWidth > 400 ? 16 : 12, // 根据屏幕宽度调整间距 }, unitOption: { paddingHorizontal: 16, paddingVertical: 8, borderRadius: 20, backgroundColor: '#F5F5F5', minWidth: 60, alignItems: 'center', }, unitOptionActive: { backgroundColor: '#4CAF50', }, unitText: { fontSize: 14, color: '#666', fontWeight: '500', }, unitTextActive: { color: '#FFFFFF', }, saveButton: { backgroundColor: '#4CAF50', marginHorizontal: screenWidth > 400 ? 24 : 16, marginBottom: 16, paddingVertical: 14, borderRadius: 12, alignItems: 'center', }, saveButtonText: { fontSize: 18, fontWeight: '600', color: '#FFFFFF', }, });