From bff2763013655a1213cdda46c77b5da5e9292556 Mon Sep 17 00:00:00 2001 From: xianyi Date: Tue, 13 Jan 2026 10:35:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E8=BF=90=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(tabs)/index.tsx | 1 + components/selection-modal.tsx | 190 +++++++++++++++++++++++++++------ 2 files changed, 156 insertions(+), 35 deletions(-) diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index b69b75e..8d50b3d 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -152,6 +152,7 @@ export default function HomeScreen() { id: s.id, label: s.name, value: s.id, + icon: s.icon, // 添加图标 }))} selectedValue={selectedSportId} onSelect={setSelectedSportId} diff --git a/components/selection-modal.tsx b/components/selection-modal.tsx index 73f9642..8e6405f 100644 --- a/components/selection-modal.tsx +++ b/components/selection-modal.tsx @@ -1,4 +1,5 @@ import { ThemedText } from "@/components/themed-text"; +import { IconSymbol } from "@/components/ui/icon-symbol"; import { Colors } from "@/constants/theme"; import { useTheme } from "@/context/ThemeContext"; import React from "react"; @@ -9,8 +10,47 @@ interface SelectionOption { id: number | string; label: string; value: any; + icon?: string; // 图标名称 } +// 运动名称到图标的映射 +const getSportIcon = (label: string, icon?: string): string => { + // 如果提供了 icon 字段,尝试直接使用 + if (icon) { + // 如果 icon 已经是 Ionicons 格式,直接返回 + if (icon.includes("-")) { + return icon; + } + } + + // 根据运动名称映射图标 + const labelLower = label.toLowerCase(); + if (labelLower.includes("足球") || labelLower.includes("football") || labelLower.includes("soccer")) { + return "football-outline"; + } + if (labelLower.includes("篮球") || labelLower.includes("basketball")) { + return "basketball-outline"; + } + if (labelLower.includes("板球") || labelLower.includes("cricket")) { + return "baseball-outline"; + } + if (labelLower.includes("网球") || labelLower.includes("tennis")) { + return "tennisball-outline"; + } + if (labelLower.includes("棒球") || labelLower.includes("baseball")) { + return "baseball-outline"; + } + if (labelLower.includes("羽毛球") || labelLower.includes("badminton")) { + return "ellipse-outline"; + } + if (labelLower.includes("斯诺克") || labelLower.includes("snooker")) { + return "radio-button-on-outline"; + } + + // 默认图标 + return "ellipse-outline"; +}; + interface SelectionModalProps { visible: boolean; onClose: () => void; @@ -47,37 +87,71 @@ export function SelectionModal({ - {title} - - - Done - + + {title} + + + - - {options.map((opt) => ( - { - onSelect(opt.value); - onClose(); - }} - > - + {options.map((opt) => { + const isSelected = selectedValue === opt.value; + const optionBg = isDark ? "#2C2C2E" : "#F5F5F5"; + const iconBg = isDark ? "#3A3A3C" : "#E5E5EA"; + + return ( + { + onSelect(opt.value); + onClose(); }} > - {opt.label} - - - ))} + {/* 左侧图标 */} + + + + + {/* 中间内容 */} + + + {opt.label} + + + {isSelected ? "已选择" : "点击切换"} + + + + {/* 右侧指示点 */} + + + ); + })} @@ -91,21 +165,67 @@ const styles = StyleSheet.create({ backgroundColor: "rgba(0,0,0,0.5)", }, sheet: { - borderTopLeftRadius: 16, - borderTopRightRadius: 16, - padding: 16, - maxHeight: "60%", + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + padding: 20, + maxHeight: "70%", }, header: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", - marginBottom: 16, + marginBottom: 20, + }, + title: { + fontSize: 18, + fontWeight: "600", + }, + closeButton: { + width: 32, + height: 32, + alignItems: "center", + justifyContent: "center", + }, + scrollView: { + maxHeight: 400, }, option: { + flexDirection: "row", + alignItems: "center", paddingVertical: 16, - paddingHorizontal: 12, - borderBottomWidth: StyleSheet.hairlineWidth, - borderBottomColor: "#ccc", + paddingHorizontal: 16, + marginBottom: 12, + borderRadius: 12, + }, + iconContainer: { + width: 48, + height: 48, + borderRadius: 24, + alignItems: "center", + justifyContent: "center", + marginRight: 12, + }, + iconPlaceholder: { + width: 24, + height: 24, + borderRadius: 12, + backgroundColor: "#999", + }, + content: { + flex: 1, + }, + optionLabel: { + fontSize: 16, + marginBottom: 4, + }, + statusText: { + fontSize: 12, + opacity: 0.6, + }, + indicator: { + width: 8, + height: 8, + borderRadius: 4, + marginLeft: 12, }, });