@@ -5,6 +5,7 @@ import React from 'react';
55import { Platform } from 'react-native' ;
66import { Tabs } from 'expo-router' ;
77import { Home , BookOpen , TrendingUp , CheckSquare , User } from 'lucide-react-native' ;
8+ import Ionicons from 'react-native-vector-icons/Ionicons' ;
89import { useTheme } from '@/contexts/ThemeContext' ;
910import type { SFSymbol } from 'sf-symbols-typescript' ;
1011import WebTopNav from '@/components/navigation/WebTopNav' ;
@@ -15,52 +16,71 @@ const NativeTabs =
1516 // eslint-disable-next-line @typescript-eslint/no-require-imports
1617 Platform . OS !== 'web' ? require ( '@/components/navigation/NativeBottomTabs' ) . NativeTabs : null ;
1718
19+ // Pre-load Android icons using Ionicons (only on Android)
20+ // These are loaded synchronously to avoid flickering during navigation
21+ const androidIcons =
22+ Platform . OS === 'android'
23+ ? {
24+ home : Ionicons . getImageSourceSync ( 'home' , 24 ) ,
25+ book : Ionicons . getImageSourceSync ( 'book' , 24 ) ,
26+ trending : Ionicons . getImageSourceSync ( 'trending-up' , 24 ) ,
27+ tasks : Ionicons . getImageSourceSync ( 'checkbox' , 24 ) ,
28+ profile : Ionicons . getImageSourceSync ( 'person' , 24 ) ,
29+ }
30+ : null ;
31+
1832// =============================================================================
1933// Types & Interfaces
2034// =============================================================================
2135
22- /** Tab route configuration with SF Symbols and Lucide fallbacks */
36+ /** Tab route configuration with SF Symbols (iOS) and Ionicons (Android) */
2337interface TabRoute {
2438 name : string ;
2539 title : string ;
2640 sfSymbol : SFSymbol ;
41+ androidIconKey : keyof NonNullable < typeof androidIcons > ;
2742 icon : React . ComponentType < { size ?: number ; color ?: string } > ;
2843}
2944
3045// =============================================================================
3146// Constants
3247// =============================================================================
3348
34- /** Tab route configuration with SF Symbols and Lucide fallbacks */
49+ /** Tab route configuration with SF Symbols (iOS) and Ionicons (Android) */
3550const tabRoutes : TabRoute [ ] = [
3651 {
3752 name : 'index' ,
3853 title : 'Home' ,
3954 sfSymbol : 'house.fill' ,
55+ androidIconKey : 'home' ,
4056 icon : Home ,
4157 } ,
4258 {
4359 name : 'steps' ,
4460 title : 'Steps' ,
4561 sfSymbol : 'book.fill' ,
62+ androidIconKey : 'book' ,
4663 icon : BookOpen ,
4764 } ,
4865 {
4966 name : 'journey' ,
5067 title : 'Journey' ,
5168 sfSymbol : 'chart.line.uptrend.xyaxis' ,
69+ androidIconKey : 'trending' ,
5270 icon : TrendingUp ,
5371 } ,
5472 {
5573 name : 'tasks' ,
5674 title : 'Tasks' ,
5775 sfSymbol : 'checklist' ,
76+ androidIconKey : 'tasks' ,
5877 icon : CheckSquare ,
5978 } ,
6079 {
6180 name : 'profile' ,
6281 title : 'Profile' ,
6382 sfSymbol : 'person.fill' ,
83+ androidIconKey : 'profile' ,
6484 icon : User ,
6585 } ,
6686] ;
@@ -127,7 +147,11 @@ export default function TabLayout(): React.ReactElement {
127147 name = { route . name }
128148 options = { {
129149 title : route . title ,
130- tabBarIcon : ( ) => ( { sfSymbol : route . sfSymbol } ) ,
150+ // iOS uses SF Symbols, Android uses pre-loaded Ionicons
151+ tabBarIcon : ( ) =>
152+ Platform . OS === 'ios'
153+ ? { sfSymbol : route . sfSymbol }
154+ : androidIcons ! [ route . androidIconKey ] ,
131155 } }
132156 />
133157 ) ) }
0 commit comments