调整详情页样式

This commit is contained in:
yuchenglong
2026-01-14 10:34:59 +08:00
parent ef7e4ae142
commit c936f3ba6b
4 changed files with 175 additions and 127 deletions

View File

@@ -9,7 +9,10 @@ interface BasketballScoreTableProps {
isDark: boolean; isDark: boolean;
} }
export function BasketballScoreTable({ data, isDark }: BasketballScoreTableProps) { export function BasketballScoreTable({
data,
isDark,
}: BasketballScoreTableProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const { match } = data; const { match } = data;
const bgColor = isDark ? "#1C1C1E" : "#FFF"; const bgColor = isDark ? "#1C1C1E" : "#FFF";
@@ -29,10 +32,10 @@ export function BasketballScoreTable({ data, isDark }: BasketballScoreTableProps
const headers = [ const headers = [
t("detail.score_table.team"), t("detail.score_table.team"),
t("detail.score_table.total"), t("detail.score_table.total"),
"Q1", "1",
"Q2", "2",
"Q3", "3",
"Q4", "4",
]; ];
const rows = [ const rows = [
@@ -84,7 +87,9 @@ export function BasketballScoreTable({ data, isDark }: BasketballScoreTableProps
{row.name} {row.name}
</ThemedText> </ThemedText>
</View> </View>
<ThemedText style={styles.cellText}>{row.total}</ThemedText> <ThemedText style={[styles.cellText, styles.totalText]}>
{row.total}
</ThemedText>
<ThemedText style={styles.cellText}>{row.q1}</ThemedText> <ThemedText style={styles.cellText}>{row.q1}</ThemedText>
<ThemedText style={styles.cellText}>{row.q2}</ThemedText> <ThemedText style={styles.cellText}>{row.q2}</ThemedText>
<ThemedText style={styles.cellText}>{row.q3}</ThemedText> <ThemedText style={styles.cellText}>{row.q3}</ThemedText>
@@ -97,54 +102,61 @@ export function BasketballScoreTable({ data, isDark }: BasketballScoreTableProps
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
margin: 16, marginHorizontal: 16,
borderRadius: 12, marginBottom: 16,
padding: 16, borderRadius: 16,
padding: 20,
elevation: 2, elevation: 2,
shadowColor: "#000", shadowColor: "#000",
shadowOffset: { width: 0, height: 2 }, shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1, shadowOpacity: 0.05,
shadowRadius: 4, shadowRadius: 8,
}, },
header: { header: {
flexDirection: "row", flexDirection: "row",
paddingBottom: 12, paddingBottom: 16,
borderBottomWidth: StyleSheet.hairlineWidth, borderBottomWidth: 1,
borderBottomColor: "rgba(150,150,150,0.2)", borderBottomColor: "rgba(150,150,150,0.1)",
}, },
headerText: { headerText: {
fontSize: 12, fontSize: 12,
fontWeight: "500", fontWeight: "600",
opacity: 0.8,
}, },
row: { row: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
paddingVertical: 12, paddingVertical: 14,
}, },
rowBorder: { rowBorder: {
borderBottomWidth: StyleSheet.hairlineWidth, borderBottomWidth: 1,
borderBottomColor: "rgba(150,150,150,0.1)", borderBottomColor: "rgba(150,150,150,0.1)",
}, },
teamCell: { teamCell: {
flex: 3, flex: 3,
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
gap: 8, gap: 10,
}, },
teamLogo: { teamLogo: {
width: 24, width: 28,
height: 24, height: 28,
resizeMode: "contain", resizeMode: "contain",
}, },
teamName: { teamName: {
flex: 1, flex: 1,
fontSize: 14, fontSize: 14,
fontWeight: "500", fontWeight: "700",
}, },
cellText: { cellText: {
flex: 1, flex: 1,
textAlign: "center", textAlign: "center",
fontSize: 14, fontSize: 14,
fontWeight: "500", fontWeight: "500",
opacity: 0.8,
},
totalText: {
fontWeight: "700",
opacity: 1,
}, },
}); });

View File

@@ -11,8 +11,10 @@ interface LeagueInfoProps {
export function LeagueInfo({ data, isDark }: LeagueInfoProps) { export function LeagueInfo({ data, isDark }: LeagueInfoProps) {
const { match } = data; const { match } = data;
const bgColor = isDark ? "#1C1C1E" : "#FFF"; // Force dark style for this component to match the header design language
const borderColor = isDark ? "#2C2C2E" : "#EEE"; const bgColor = "#121212";
const borderColor = "rgba(255,255,255,0.1)";
const textColor = "#FFF";
return ( return (
<TouchableOpacity <TouchableOpacity
@@ -26,26 +28,15 @@ export function LeagueInfo({ data, isDark }: LeagueInfoProps) {
{match.leagueLogo ? ( {match.leagueLogo ? (
<Image source={{ uri: match.leagueLogo }} style={styles.leagueLogo} /> <Image source={{ uri: match.leagueLogo }} style={styles.leagueLogo} />
) : ( ) : (
<View <View style={[styles.fallbackLogo, { backgroundColor: "#333" }]}>
style={[ <IconSymbol name="trophy-outline" size={14} color="#AAA" />
styles.fallbackLogo,
{ backgroundColor: isDark ? "#333" : "#F0F0F0" },
]}
>
<IconSymbol
name="trophy-outline"
size={14}
color={isDark ? "#AAA" : "#888"}
/>
</View> </View>
)} )}
<ThemedText style={styles.leagueName}>{match.leagueName}</ThemedText> <ThemedText style={[styles.leagueName, { color: textColor }]}>
{match.leagueName}
</ThemedText>
</View> </View>
<IconSymbol <IconSymbol name="chevron-forward" size={16} color="#888" />
name="chevron-forward"
size={16}
color={isDark ? "#666" : "#CCC"}
/>
</TouchableOpacity> </TouchableOpacity>
); );
} }
@@ -56,7 +47,7 @@ const styles = StyleSheet.create({
alignItems: "center", alignItems: "center",
justifyContent: "space-between", justifyContent: "space-between",
paddingHorizontal: 16, paddingHorizontal: 16,
paddingVertical: 12, paddingVertical: 14,
borderBottomWidth: 1, borderBottomWidth: 1,
}, },
left: { left: {

View File

@@ -1,4 +1,5 @@
import { ThemedText } from "@/components/themed-text"; import { ThemedText } from "@/components/themed-text";
import { IconSymbol, IconSymbolName } from "@/components/ui/icon-symbol";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { ScrollView, StyleSheet, TouchableOpacity, View } from "react-native"; import { ScrollView, StyleSheet, TouchableOpacity, View } from "react-native";
@@ -10,35 +11,62 @@ interface MatchTabsProps {
sportId: number; sportId: number;
} }
export function MatchTabs({ activeTab, onTabChange, isDark, sportId }: MatchTabsProps) { export function MatchTabs({
activeTab,
onTabChange,
isDark,
sportId,
}: MatchTabsProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const containerBg = isDark ? "#121212" : "#F8F8F8"; const containerBg = isDark ? "#121212" : "#F5F5F5";
// 根据 sportId 动态生成标签 // 根据 sportId 动态生成标签
const getTabs = () => { const getTabs = () => {
// 使用 Ionicons 名称
const commonTabs = [
{
id: "info",
label: t("detail.tabs.info"),
icon: "document-text-outline",
},
{
id: "h2h",
label: t("detail.tabs.h2h"),
icon: "swap-horizontal-outline",
},
{ id: "chat", label: t("detail.tabs.chat"), icon: "chatbubbles-outline" },
];
if (sportId === 1) { if (sportId === 1) {
// 足球: 详情、统计数据、赔率、交锋往绩、聊天 // 足球: 详情、统计数据、赔率、交锋往绩、聊天
return [ return [
{ id: "info", label: t("detail.tabs.info") }, {
{ id: "stats", label: t("detail.tabs.stats") }, id: "info",
{ id: "odds", label: t("detail.tabs.odds") }, label: t("detail.tabs.info"),
{ id: "h2h", label: t("detail.tabs.h2h") }, icon: "document-text-outline",
{ id: "chat", label: t("detail.tabs.chat") }, },
{
id: "stats",
label: t("detail.tabs.stats"),
icon: "stats-chart-outline",
},
{ id: "odds", label: t("detail.tabs.odds"), icon: "cash-outline" },
{
id: "h2h",
label: t("detail.tabs.h2h"),
icon: "swap-horizontal-outline",
},
{
id: "chat",
label: t("detail.tabs.chat"),
icon: "chatbubbles-outline",
},
]; ];
} else if (sportId === 2) { } else if (sportId === 2) {
// 篮球: 详情、交锋往绩、聊天 // 篮球
return [ return commonTabs;
{ id: "info", label: t("detail.tabs.info") },
{ id: "h2h", label: t("detail.tabs.h2h") },
{ id: "chat", label: t("detail.tabs.chat") },
];
} }
// 默认: 详情、交锋往绩、聊天 return commonTabs;
return [
{ id: "info", label: t("detail.tabs.info") },
{ id: "h2h", label: t("detail.tabs.h2h") },
{ id: "chat", label: t("detail.tabs.chat") },
];
}; };
const tabs = getTabs(); const tabs = getTabs();
@@ -52,23 +80,40 @@ export function MatchTabs({ activeTab, onTabChange, isDark, sportId }: MatchTabs
> >
{tabs.map((tab) => { {tabs.map((tab) => {
const isActive = activeTab === tab.id; const isActive = activeTab === tab.id;
const activeColor = "#FF9800"; // 橙色
const inactiveColor = isDark ? "#AAA" : "#666"; // 增强对比度
const inactiveBg = isDark
? "rgba(255,255,255,0.05)"
: "rgba(0,0,0,0.03)";
return ( return (
<TouchableOpacity <TouchableOpacity
key={tab.id} key={tab.id}
onPress={() => onTabChange(tab.id)} onPress={() => onTabChange(tab.id)}
style={[ style={[
styles.tabBtn, styles.tabBtn,
isActive && styles.activeTabBtn, {
isActive && { backgroundColor: isActive
backgroundColor: isDark ? "rgba(255,255,255,0.05)" : "#FFF", ? isDark
? "#2C2C2E"
: "#FFF"
: inactiveBg,
}, },
]} ]}
> >
<IconSymbol
name={tab.icon as IconSymbolName}
size={16}
color={isActive ? activeColor : inactiveColor}
style={{ marginRight: 6 }}
/>
<ThemedText <ThemedText
style={[ style={[
styles.tabText, styles.tabText,
isActive && styles.activeTabText, {
isActive && { color: "#FF9800" }, color: isActive ? activeColor : inactiveColor,
fontWeight: isActive ? "700" : "500", // 强化选中粗体
},
]} ]}
> >
{tab.label} {tab.label}
@@ -83,34 +128,23 @@ export function MatchTabs({ activeTab, onTabChange, isDark, sportId }: MatchTabs
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
paddingVertical: 12, paddingVertical: 8,
}, },
scrollContent: { scrollContent: {
paddingHorizontal: 16, paddingHorizontal: 16,
gap: 12, gap: 10,
alignItems: "center", // 确保所有 tabBtn 垂直对齐
}, },
tabBtn: { tabBtn: {
paddingHorizontal: 20, flexDirection: "row",
paddingVertical: 8, alignItems: "center",
justifyContent: "center",
paddingHorizontal: 15,
paddingVertical: 6,
borderRadius: 20, borderRadius: 20,
borderWidth: 1,
borderColor: "transparent",
},
activeTabBtn: {
borderColor: "rgba(255,152,0,0.3)",
// Shadow for iOS/Android if needed
elevation: 2,
shadowColor: "#000",
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
}, },
tabText: { tabText: {
fontSize: 14, fontSize: 14,
fontWeight: "500", includeFontPadding: false, // 移除 Android 字体默认内边距
opacity: 0.6,
},
activeTabText: {
opacity: 1,
}, },
}); });

View File

@@ -20,8 +20,10 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
return ( return (
<LinearGradient <LinearGradient
colors={["#1A2138", "#2A3C5B"]} colors={["#521e10", "#0e0e10"]}
style={[styles.container, { paddingTop: Math.max(topInset, 20) }]} start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
style={[styles.container, { paddingTop: Math.max(topInset, 10) }]}
> >
{/* Top Bar */} {/* Top Bar */}
<View style={styles.topBar}> <View style={styles.topBar}>
@@ -30,7 +32,7 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
onPress={() => router.back()} onPress={() => router.back()}
style={styles.iconBtn} style={styles.iconBtn}
> >
<IconSymbol name="chevron-back" size={24} color="#FFF" /> <IconSymbol name="chevron-back" size={28} color="#FFF" />
</TouchableOpacity> </TouchableOpacity>
</View> </View>
@@ -42,10 +44,10 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
<View style={styles.rightContainer}> <View style={styles.rightContainer}>
<TouchableOpacity style={styles.iconBtn}> <TouchableOpacity style={styles.iconBtn}>
<IconSymbol name="notifications-outline" size={22} color="#FFF" /> <IconSymbol name="notifications-outline" size={24} color="#FFF" />
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.iconBtn}> <TouchableOpacity style={styles.iconBtn}>
<IconSymbol name="star-outline" size={22} color="#FFF" /> <IconSymbol name="star-outline" size={24} color="#FFF" />
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>
@@ -69,7 +71,7 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
<ThemedText style={styles.scoreValue}> <ThemedText style={styles.scoreValue}>
{match.eventFinalResult && match.eventFinalResult !== "-" {match.eventFinalResult && match.eventFinalResult !== "-"
? match.eventFinalResult ? match.eventFinalResult
: "0 - 0"} : "0-0"}
</ThemedText> </ThemedText>
</View> </View>
<TouchableOpacity style={styles.fieldBtn}> <TouchableOpacity style={styles.fieldBtn}>
@@ -95,14 +97,14 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
paddingBottom: 30, paddingBottom: 24,
paddingHorizontal: 16, paddingHorizontal: 16,
}, },
topBar: { topBar: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
marginBottom: 20, marginBottom: 16,
minHeight: 40, minHeight: 44,
}, },
leftContainer: { leftContainer: {
flex: 1, flex: 1,
@@ -119,78 +121,87 @@ const styles = StyleSheet.create({
flexDirection: "row", flexDirection: "row",
justifyContent: "flex-end", justifyContent: "flex-end",
alignItems: "center", alignItems: "center",
gap: 12, gap: 4,
}, },
statusText: { statusText: {
color: "#FFF", color: "#FFF",
fontSize: 16, fontSize: 17,
fontWeight: "600", fontWeight: "600",
opacity: 0.8, opacity: 0.9,
},
rightIcons: {
flexDirection: "row",
gap: 12,
}, },
iconBtn: { iconBtn: {
width: 36, width: 40,
height: 36, height: 40,
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
borderRadius: 20,
backgroundColor: "rgba(255,255,255,0.1)",
marginHorizontal: 4,
}, },
scoreRow: { scoreRow: {
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "flex-start",
justifyContent: "space-between", justifyContent: "space-between",
paddingHorizontal: 10, paddingHorizontal: 0,
marginTop: 10,
}, },
teamInfo: { teamInfo: {
flex: 1.2, flex: 1,
alignItems: "center", alignItems: "center",
}, },
logoContainer: { logoContainer: {
width: 64, width: 70,
height: 64, height: 70,
borderRadius: 32, marginBottom: 10,
backgroundColor: "rgba(255,255,255,0.1)",
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
marginBottom: 8,
overflow: "hidden",
}, },
teamLogo: { teamLogo: {
width: 48, width: 60,
height: 48, height: 60,
resizeMode: "contain", resizeMode: "contain",
}, },
teamName: { teamName: {
color: "#FFF", color: "#FFF",
fontSize: 14, fontSize: 14,
fontWeight: "600", fontWeight: "700",
textAlign: "center", textAlign: "center",
lineHeight: 18,
}, },
centerScore: { centerScore: {
flex: 1, flex: 1.4,
alignItems: "center", alignItems: "center",
paddingTop: 8,
}, },
scoreBox: { scoreBox: {
backgroundColor: "#FFF", backgroundColor: "#FFF",
borderRadius: 12, borderRadius: 16,
paddingHorizontal: 16, paddingHorizontal: 24,
paddingVertical: 8, paddingVertical: 12,
marginBottom: 12, marginBottom: 16,
minWidth: 100,
alignItems: "center",
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 4,
elevation: 4,
}, },
scoreValue: { scoreValue: {
color: "#000", color: "#000",
fontSize: 19, fontSize: 30,
fontWeight: "bold", fontWeight: "700",
letterSpacing: 2, lineHeight: 30,
letterSpacing: 1,
}, },
fieldBtn: { fieldBtn: {
backgroundColor: "#0055FF", backgroundColor: "#0044FF",
width: 80, width: 60,
height: 28, height: 32,
borderRadius: 14, borderRadius: 16,
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
borderWidth: 1,
borderColor: "rgba(255,255,255,0.2)",
}, },
}); });