fix(ui): resolve status bar overlay issue across all screens

Add SafeAreaProvider to root layout and implement proper safe area handling:
- Wrap app in SafeAreaProvider in _layout.tsx
- Update HomeScreen to use safe area insets for proper top padding
- Fix SettingsScreen safe area handling for all device types
- Update ResponsiveHeader to use SafeAreaContext instead of manual calculation

This ensures content is not covered by the status bar on mobile and tablet devices while maintaining TV compatibility.
This commit is contained in:
zimplexing
2025-08-13 19:23:32 +08:00
parent 5b6631624d
commit cdf0d72bdc
4 changed files with 31 additions and 25 deletions

View File

@@ -5,6 +5,7 @@ import * as SplashScreen from "expo-splash-screen";
import { useEffect } from "react";
import { Platform, View, StyleSheet } from "react-native";
import Toast from "react-native-toast-message";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { useSettingsStore } from "@/stores/settingsStore";
import { useRemoteControlStore } from "@/stores/remoteControlStore";
@@ -76,23 +77,25 @@ export default function RootLayout() {
}
return (
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<View style={styles.container}>
<Stack>
<Stack.Screen name="index" options={{ headerShown: false }} />
<Stack.Screen name="detail" options={{ headerShown: false }} />
{Platform.OS !== "web" && <Stack.Screen name="play" options={{ headerShown: false }} />}
<Stack.Screen name="search" options={{ headerShown: false }} />
<Stack.Screen name="live" options={{ headerShown: false }} />
<Stack.Screen name="settings" options={{ headerShown: false }} />
<Stack.Screen name="favorites" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
</View>
<Toast />
<LoginModal />
<UpdateModal />
</ThemeProvider>
<SafeAreaProvider>
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<View style={styles.container}>
<Stack>
<Stack.Screen name="index" options={{ headerShown: false }} />
<Stack.Screen name="detail" options={{ headerShown: false }} />
{Platform.OS !== "web" && <Stack.Screen name="play" options={{ headerShown: false }} />}
<Stack.Screen name="search" options={{ headerShown: false }} />
<Stack.Screen name="live" options={{ headerShown: false }} />
<Stack.Screen name="settings" options={{ headerShown: false }} />
<Stack.Screen name="favorites" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
</View>
<Toast />
<LoginModal />
<UpdateModal />
</ThemeProvider>
</SafeAreaProvider>
);
}

View File

@@ -187,7 +187,7 @@ export default function HomeScreen() {
const dynamicStyles = StyleSheet.create({
container: {
flex: 1,
paddingTop: deviceType === "mobile" ? 0 : 40,
paddingTop: deviceType === "mobile" ? insets.top : deviceType === "tablet" ? insets.top + 20 : 40,
},
headerContainer: {
flexDirection: "row",

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect, useRef } from "react";
import { View, StyleSheet, FlatList, Alert, KeyboardAvoidingView, Platform } from "react-native";
import { useTVEventHandler } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { ThemedText } from "@/components/ThemedText";
import { ThemedView } from "@/components/ThemedView";
import { StyledButton } from "@/components/StyledButton";
@@ -24,6 +25,7 @@ export default function SettingsScreen() {
const { loadSettings, saveSettings, setApiBaseUrl, setM3uUrl } = useSettingsStore();
const { lastMessage, targetPage, clearMessage } = useRemoteControlStore();
const backgroundColor = useThemeColor({}, "background");
const insets = useSafeAreaInsets();
// 响应式布局配置
const responsiveConfig = useResponsiveLayout();
@@ -162,7 +164,7 @@ export default function SettingsScreen() {
useTVEventHandler(deviceType === "tv" ? handleTVEvent : () => {});
// 动态样式
const dynamicStyles = createResponsiveStyles(deviceType, spacing);
const dynamicStyles = createResponsiveStyles(deviceType, spacing, insets);
const renderSettingsContent = () => (
<KeyboardAvoidingView style={{ flex: 1, backgroundColor }} behavior={Platform.OS === "ios" ? "padding" : "height"}>
@@ -214,7 +216,7 @@ export default function SettingsScreen() {
);
}
const createResponsiveStyles = (deviceType: string, spacing: number) => {
const createResponsiveStyles = (deviceType: string, spacing: number, insets: any) => {
const isMobile = deviceType === "mobile";
const isTablet = deviceType === "tablet";
const isTV = deviceType === "tv";
@@ -224,7 +226,7 @@ const createResponsiveStyles = (deviceType: string, spacing: number) => {
container: {
flex: 1,
padding: spacing,
paddingTop: isTV ? spacing * 2 : 0,
paddingTop: isTV ? spacing * 2 : isMobile ? insets.top + spacing : insets.top + spacing * 1.5,
},
header: {
flexDirection: "row",