Files
rn-app/app/theme-test.tsx
2025-11-06 16:37:01 +08:00

318 lines
10 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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',
},
});