fix: Prevent tab bar from being overlapped by Android navigation buttons
- Add SafeAreaProvider wrapper in root layout for reliable insets on Android - Add minimum 16px bottom padding on Android to prevent overlap with gesture navigation or software buttons (Samsung, Pixel, etc.) - Keep 10px minimum for other platforms 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
fa5d4ffb23
commit
5d2e8c029f
@ -1,5 +1,6 @@
|
|||||||
import { Tabs } from 'expo-router';
|
import { Tabs } from 'expo-router';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Platform } from 'react-native';
|
||||||
import { Feather } from '@expo/vector-icons';
|
import { Feather } from '@expo/vector-icons';
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
|
|
||||||
@ -13,10 +14,13 @@ export default function TabLayout() {
|
|||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
// Calculate tab bar height based on safe area
|
// Calculate tab bar height based on safe area
|
||||||
// On Android with navigation buttons (Samsung), insets.bottom is the nav bar height
|
|
||||||
// On iOS with home indicator, insets.bottom is ~34px
|
// On iOS with home indicator, insets.bottom is ~34px
|
||||||
// Minimum padding of 10px for devices without safe area
|
// On Android with gesture navigation or software buttons (Samsung/Pixel):
|
||||||
const bottomPadding = Math.max(insets.bottom, 10);
|
// - insets.bottom should reflect the navigation bar height
|
||||||
|
// - But some devices/modes may return 0, so we add a minimum for Android
|
||||||
|
// Android minimum: 16px to ensure content doesn't touch system buttons
|
||||||
|
const androidMinPadding = Platform.OS === 'android' ? 16 : 0;
|
||||||
|
const bottomPadding = Math.max(insets.bottom, androidMinPadding, 10);
|
||||||
const tabBarHeight = 60 + bottomPadding; // 60px for content + safe area padding
|
const tabBarHeight = 60 + bottomPadding; // 60px for content + safe area padding
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { StatusBar } from 'expo-status-bar';
|
|||||||
import * as SplashScreen from 'expo-splash-screen';
|
import * as SplashScreen from 'expo-splash-screen';
|
||||||
import 'react-native-reanimated';
|
import 'react-native-reanimated';
|
||||||
import { KeyboardProvider } from 'react-native-keyboard-controller';
|
import { KeyboardProvider } from 'react-native-keyboard-controller';
|
||||||
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
|
|
||||||
import { useColorScheme } from '@/hooks/use-color-scheme';
|
import { useColorScheme } from '@/hooks/use-color-scheme';
|
||||||
import { AuthProvider, useAuth } from '@/contexts/AuthContext';
|
import { AuthProvider, useAuth } from '@/contexts/AuthContext';
|
||||||
@ -63,16 +64,18 @@ function RootLayoutNav() {
|
|||||||
|
|
||||||
export default function RootLayout() {
|
export default function RootLayout() {
|
||||||
return (
|
return (
|
||||||
<KeyboardProvider>
|
<SafeAreaProvider>
|
||||||
<AuthProvider>
|
<KeyboardProvider>
|
||||||
<BeneficiaryProvider>
|
<AuthProvider>
|
||||||
<VoiceTranscriptProvider>
|
<BeneficiaryProvider>
|
||||||
<VoiceCallProvider>
|
<VoiceTranscriptProvider>
|
||||||
<RootLayoutNav />
|
<VoiceCallProvider>
|
||||||
</VoiceCallProvider>
|
<RootLayoutNav />
|
||||||
</VoiceTranscriptProvider>
|
</VoiceCallProvider>
|
||||||
</BeneficiaryProvider>
|
</VoiceTranscriptProvider>
|
||||||
</AuthProvider>
|
</BeneficiaryProvider>
|
||||||
</KeyboardProvider>
|
</AuthProvider>
|
||||||
|
</KeyboardProvider>
|
||||||
|
</SafeAreaProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user