318 lines
10 KiB
TypeScript
318 lines
10 KiB
TypeScript
import { StyleSheet, ScrollView, TouchableOpacity, View, Text, useColorScheme as useSystemColorScheme } from 'react-native';
|
||
import { Stack } from 'expo-router';
|
||
import { useState, useEffect, useMemo } from 'react';
|
||
import { useTheme, useSettingsActions } from '@/stores';
|
||
import { useHaptics } from '@/hooks';
|
||
import Colors from '@/constants/Colors';
|
||
|
||
export default function ThemeTestScreen() {
|
||
const currentTheme = useTheme();
|
||
const { setTheme } = useSettingsActions();
|
||
const haptics = useHaptics();
|
||
const systemColorScheme = useSystemColorScheme();
|
||
|
||
// 强制重新渲染的状态
|
||
const [renderKey, setRenderKey] = useState(0);
|
||
|
||
// 直接计算实际应用的主题 - 不使用 useColorScheme hook
|
||
const actualTheme: 'light' | 'dark' = useMemo(() => {
|
||
return currentTheme === 'auto'
|
||
? (systemColorScheme === 'dark' ? 'dark' : 'light')
|
||
: currentTheme;
|
||
}, [currentTheme, systemColorScheme]);
|
||
|
||
// 使用 useMemo 确保颜色对象在主题改变时重新计算
|
||
const colors = useMemo(() => {
|
||
console.log('🎨 Recalculating colors for theme:', actualTheme);
|
||
return Colors[actualTheme] as Record<string, any>;
|
||
}, [actualTheme]);
|
||
|
||
// 监听主题变化
|
||
useEffect(() => {
|
||
console.log('🎨 Theme changed:', { currentTheme, systemColorScheme, actualTheme, renderKey });
|
||
setRenderKey(prev => prev + 1);
|
||
}, [currentTheme, systemColorScheme, actualTheme]);
|
||
|
||
const handleThemeChange = (newTheme: 'light' | 'dark' | 'auto') => {
|
||
haptics.selection();
|
||
console.log('🎨 Changing theme to:', newTheme);
|
||
setTheme(newTheme);
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<Stack.Screen
|
||
options={{
|
||
title: '主题测试',
|
||
headerStyle: {
|
||
backgroundColor: colors.background,
|
||
},
|
||
headerTintColor: colors.text,
|
||
}}
|
||
/>
|
||
<ScrollView
|
||
style={[styles.container, { backgroundColor: colors.background }]}
|
||
>
|
||
{/* 主题信息 */}
|
||
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
||
<Text style={[styles.title, { color: colors.text }]}>
|
||
当前主题信息
|
||
</Text>
|
||
<Text style={[styles.infoText, { color: colors.textSecondary }]}>
|
||
用户设置: {currentTheme}
|
||
</Text>
|
||
<Text style={[styles.infoText, { color: colors.textSecondary }]}>
|
||
系统主题: {systemColorScheme || 'light'}
|
||
</Text>
|
||
<Text style={[styles.infoText, { color: colors.textSecondary }]}>
|
||
实际应用: {actualTheme}
|
||
</Text>
|
||
<Text style={[styles.infoText, { color: colors.textSecondary }]}>
|
||
渲染次数: {renderKey}
|
||
</Text>
|
||
</View>
|
||
|
||
{/* 主题切换按钮 */}
|
||
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
||
<Text style={[styles.title, { color: colors.text }]}>
|
||
切换主题
|
||
</Text>
|
||
<View style={styles.buttonRow}>
|
||
<TouchableOpacity
|
||
style={[
|
||
styles.themeButton,
|
||
{
|
||
backgroundColor: currentTheme === 'light' ? colors.primary : colors.backgroundTertiary,
|
||
borderColor: colors.border,
|
||
}
|
||
]}
|
||
onPress={() => handleThemeChange('light')}
|
||
>
|
||
<Text style={[
|
||
styles.buttonText,
|
||
{ color: currentTheme === 'light' ? '#fff' : colors.text }
|
||
]}>
|
||
☀️ 浅色
|
||
</Text>
|
||
</TouchableOpacity>
|
||
|
||
<TouchableOpacity
|
||
style={[
|
||
styles.themeButton,
|
||
{
|
||
backgroundColor: currentTheme === 'dark' ? colors.primary : colors.backgroundTertiary,
|
||
borderColor: colors.border,
|
||
}
|
||
]}
|
||
onPress={() => handleThemeChange('dark')}
|
||
>
|
||
<Text style={[
|
||
styles.buttonText,
|
||
{ color: currentTheme === 'dark' ? '#fff' : colors.text }
|
||
]}>
|
||
🌙 深色
|
||
</Text>
|
||
</TouchableOpacity>
|
||
|
||
<TouchableOpacity
|
||
style={[
|
||
styles.themeButton,
|
||
{
|
||
backgroundColor: currentTheme === 'auto' ? colors.primary : colors.backgroundTertiary,
|
||
borderColor: colors.border,
|
||
}
|
||
]}
|
||
onPress={() => handleThemeChange('auto')}
|
||
>
|
||
<Text style={[
|
||
styles.buttonText,
|
||
{ color: currentTheme === 'auto' ? '#fff' : colors.text }
|
||
]}>
|
||
🔄 自动
|
||
</Text>
|
||
</TouchableOpacity>
|
||
</View>
|
||
</View>
|
||
|
||
{/* 文本颜色展示 */}
|
||
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
||
<Text style={[styles.title, { color: colors.text }]}>
|
||
文本颜色
|
||
</Text>
|
||
<Text style={[styles.colorText, { color: colors.text }]}>
|
||
Primary Text - {colors.text}
|
||
</Text>
|
||
<Text style={[styles.colorText, { color: colors.textSecondary }]}>
|
||
Secondary Text - {colors.textSecondary}
|
||
</Text>
|
||
<Text style={[styles.colorText, { color: colors.textTertiary }]}>
|
||
Tertiary Text - {colors.textTertiary}
|
||
</Text>
|
||
</View>
|
||
|
||
{/* 背景颜色展示 */}
|
||
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
||
<Text style={[styles.title, { color: colors.text }]}>
|
||
背景颜色
|
||
</Text>
|
||
<View style={[styles.colorBox, { backgroundColor: colors.background }]}>
|
||
<Text style={[styles.colorText, { color: colors.text }]}>
|
||
Primary Background - {colors.background}
|
||
</Text>
|
||
</View>
|
||
<View style={[styles.colorBox, { backgroundColor: colors.backgroundSecondary, borderWidth: 1, borderColor: colors.border }]}>
|
||
<Text style={[styles.colorText, { color: colors.text }]}>
|
||
Secondary Background - {colors.backgroundSecondary}
|
||
</Text>
|
||
</View>
|
||
<View style={[styles.colorBox, { backgroundColor: colors.backgroundTertiary }]}>
|
||
<Text style={[styles.colorText, { color: colors.text }]}>
|
||
Tertiary Background - {colors.backgroundTertiary}
|
||
</Text>
|
||
</View>
|
||
</View>
|
||
|
||
{/* 主题颜色展示 */}
|
||
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
||
<Text style={[styles.title, { color: colors.text }]}>
|
||
主题颜色
|
||
</Text>
|
||
<View style={styles.colorGrid}>
|
||
<View style={[styles.colorBox, { backgroundColor: colors.primary }]}>
|
||
<Text style={[styles.colorText, { color: '#fff' }]}>Primary - {colors.primary}</Text>
|
||
</View>
|
||
<View style={[styles.colorBox, { backgroundColor: colors.secondary }]}>
|
||
<Text style={[styles.colorText, { color: '#fff' }]}>Secondary - {colors.secondary}</Text>
|
||
</View>
|
||
<View style={[styles.colorBox, { backgroundColor: colors.success }]}>
|
||
<Text style={[styles.colorText, { color: '#fff' }]}>Success - {colors.success}</Text>
|
||
</View>
|
||
<View style={[styles.colorBox, { backgroundColor: colors.warning }]}>
|
||
<Text style={[styles.colorText, { color: '#fff' }]}>Warning - {colors.warning}</Text>
|
||
</View>
|
||
<View style={[styles.colorBox, { backgroundColor: colors.error }]}>
|
||
<Text style={[styles.colorText, { color: '#fff' }]}>Error - {colors.error}</Text>
|
||
</View>
|
||
<View style={[styles.colorBox, { backgroundColor: colors.info }]}>
|
||
<Text style={[styles.colorText, { color: '#fff' }]}>Info - {colors.info}</Text>
|
||
</View>
|
||
</View>
|
||
</View>
|
||
|
||
{/* UI 元素展示 */}
|
||
<View style={[styles.section, { backgroundColor: colors.backgroundSecondary }]}>
|
||
<Text style={[styles.title, { color: colors.text }]}>
|
||
UI 元素
|
||
</Text>
|
||
<View style={[styles.card, { backgroundColor: colors.card, borderColor: colors.border }]}>
|
||
<Text style={[styles.cardText, { color: colors.text }]}>
|
||
这是一个卡片组件
|
||
</Text>
|
||
<Text style={[styles.cardSubtext, { color: colors.textSecondary }]}>
|
||
卡片背景色: {colors.card}
|
||
</Text>
|
||
</View>
|
||
|
||
<View style={[styles.input, { backgroundColor: colors.inputBackground, borderColor: colors.inputBorder }]}>
|
||
<Text style={[styles.inputText, { color: colors.textSecondary }]}>
|
||
输入框样式预览
|
||
</Text>
|
||
</View>
|
||
|
||
<View style={[styles.separator, { backgroundColor: colors.separator }]} />
|
||
|
||
<TouchableOpacity style={[styles.button, { backgroundColor: colors.buttonPrimary }]}>
|
||
<Text style={[styles.buttonText, { color: '#fff' }]}>
|
||
按钮示例
|
||
</Text>
|
||
</TouchableOpacity>
|
||
</View>
|
||
</ScrollView>
|
||
</>
|
||
);
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
container: {
|
||
flex: 1,
|
||
},
|
||
section: {
|
||
margin: 16,
|
||
padding: 16,
|
||
borderRadius: 12,
|
||
},
|
||
title: {
|
||
fontSize: 20,
|
||
fontWeight: 'bold',
|
||
marginBottom: 16,
|
||
},
|
||
infoText: {
|
||
fontSize: 16,
|
||
marginBottom: 8,
|
||
},
|
||
buttonRow: {
|
||
flexDirection: 'row',
|
||
gap: 12,
|
||
},
|
||
themeButton: {
|
||
flex: 1,
|
||
paddingVertical: 12,
|
||
paddingHorizontal: 16,
|
||
borderRadius: 8,
|
||
borderWidth: 2,
|
||
alignItems: 'center',
|
||
},
|
||
buttonText: {
|
||
fontSize: 16,
|
||
fontWeight: '600',
|
||
},
|
||
colorText: {
|
||
fontSize: 14,
|
||
marginBottom: 8,
|
||
fontFamily: 'monospace',
|
||
},
|
||
colorBox: {
|
||
padding: 16,
|
||
borderRadius: 8,
|
||
marginBottom: 8,
|
||
alignItems: 'center',
|
||
},
|
||
colorGrid: {
|
||
gap: 8,
|
||
},
|
||
card: {
|
||
padding: 16,
|
||
borderRadius: 8,
|
||
borderWidth: 1,
|
||
marginBottom: 12,
|
||
},
|
||
cardText: {
|
||
fontSize: 16,
|
||
fontWeight: '600',
|
||
marginBottom: 4,
|
||
},
|
||
cardSubtext: {
|
||
fontSize: 12,
|
||
fontFamily: 'monospace',
|
||
},
|
||
input: {
|
||
padding: 12,
|
||
borderRadius: 8,
|
||
borderWidth: 1,
|
||
marginBottom: 12,
|
||
},
|
||
inputText: {
|
||
fontSize: 14,
|
||
},
|
||
separator: {
|
||
height: 1,
|
||
marginVertical: 12,
|
||
},
|
||
button: {
|
||
padding: 16,
|
||
borderRadius: 8,
|
||
alignItems: 'center',
|
||
},
|
||
});
|
||
|