I've been working on designing a navigation header similar to the Apple Contacts app, with a large title and search function, but only for the Home Screen. All other tabs should have their own unique settings, like different titles or hidden navigation bars. Although I've built what I believe is a solid foundation, I'm facing challenges in getting the search and large title settings to work properly. You can find the reproducible repository here.
My overall project structure has an entry point that directs to /apps/_layout.tsx
:
import { Stack } from 'expo-router';
export default function Layout() {
return (
<Stack screenOptions={{ headerShown: false }}>
<Stack.Screen name="(tabs)" />
</Stack>
);
}
The main layout leads to the first stack, which is a tab view containing the main app. It's located at /apps/(tabs)/_layout.tsx
and looks like this:
import { BlurView } from 'expo-blur';
import { Tabs } from 'expo-router';
import { SafeAreaProvider } from 'react-native-safe-area-context';
export default function TabsLayout() {
return (
<SafeAreaProvider>
<Tabs
screenOptions={{
tabBarStyle: { position: 'absolute', elevation: 0 },
tabBarBackground: () =>
<BlurView tint="prominent" intensity={100} style={StyleSheet.absoluteFill} />
}}>
<Tabs.Screen name="index" />
<Tabs.Screen name="tab2" />
</Tabs>
</SafeAreaProvider>
);
}
The first tab is the index page located at /apps/(tabs)/index.tsx
and it appears as follows:
import { BottomTabBarHeightContext, useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
import { useHeaderHeight } from '@react-navigation/elements';
import { BlurView } from 'expo-blur';
import { Stack } from 'expo-router';
import { ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Text, StyleSheet } from 'react-native';
export default function Home() {
const items = Array.from({ length: 60 }, (_, index) => index);
const headerHeight = useHeaderHeight();
const bottomTabBarHeight = useBottomTabBarHeight();
return (
<ScrollView style={{ flex: 1, backgroundColor: 'blue' }}>
<Stack.Screen
options={{
headerShown: true,
headerTransparent: true,
headerBackground: () =>
<BlurView tint="prominent" intensity={100} style={StyleSheet.absoluteFill} />
}}
/>
<SafeAreaView
edges={['left', 'right']}
style={{
flex: 1,
backgroundColor: 'green',
paddingTop: headerHeight,
paddingBottom: bottomTabBarHeight
}}
>
{items.map((item, index) => (
<Text key={index} style={{...}}>{`Item ${item}`}</Text>
))}
</SafeAreaView>
</ScrollView>
);
}
This setup provides a solid native foundation where content extends under the header and bottom tabs, allowing the content to scroll beneath them.
https://i.stack.imgur.com/gJGNE.gif
It even functions well in landscape orientation, which is promising:
https://i.stack.imgur.com/1T4xH.gif
Now, my goal is to implement a large title and add a search bar in the navigation bar, similar to the Apple Contacts app:
https://i.stack.imgur.com/iIcTC.gif
I've tried adding the following code snippets in different areas, but they don't seem to have any effect:
headerLargeTitle: true,
headerSearchBarOptions: {
placeholder: 'Search'
}
The documentation on this topic is limited, and the examples provided are either outdated or not relevant to the file-based Expo Router v3. As it differs from React Navigation, the documentation for React Navigation doesn't align with Expo Router's usage. Could it be that my project structure is incorrect? Any assistance or insight would be greatly appreciated!