iOS - Expo Router v3 ტაბ ნავიგაცია სტეკით, ძიებით და დიდ სათაურს
მეცვინება მობილური Apple Contacts-ის ნავიგაციის ჰედერის გაბატონება საძიებელი ველით და დიდი სათაურით, მაგრამ მხოლოდ მთავარი ეკრანზე. ყველა სხვა ტაბს უნდა ჰქონდეს საკუთარი პარამეტრები, როგორიცაა სხვადასხვა სათაური ან ზოგჯერ ნავიგაციის ბარის დამალვა. ვფიქრობ, მყარ საფუძველზე დავდგი, მაგრამ საძიებელი და დიდი სათაურის პარამეტრები არ მუშაობს. გამეორებადი რეპო აქ არის.
საერთოდ, ჩემი სტრუქტურა არის შესვლის წერტილი, რომელიც მიუთითებს /apps/_layout.tsx-ზე:
import { Stack } from 'expo-router';
export default function Layout() {
return (
<Stack screenOptions={{ headerShown: false }}>
<Stack.Screen name="(tabs)" />
</Stack>
);
}
მთავარი ლეაუთი მიუთითებს პირველ სტეკზე, რომელიც არის ტაბის ხედვა, სადაც განთავსებულია მთავარი აპი, ეს მდებარეობს /apps/(tabs)/_layout.tsx და შემდეგნაირად არის:
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>
);
}
პირველი ჩანართი არის ინდექსის გვერდი /apps/(tabs)/index.tsx და შემდეგნაირად:
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>
);
}
ეს მიგვიყვანა კარგ, მშობლიურ საფუძვლამდე, სადაც კონტენტი ვრცელდება ჰედერისა და ქვედა ტაბების ქვეშ და კონტენტი იხედება მათი ქვეშ.
ის მუშაობს ასევე ლანდშაფტის ორიანტაციაში, რაც კარგი ნიშანია:
ახლა ვცდილობ გავუკეთო სათაური დიდად და დავამატო საძიებო ზოლი ნავბარში, როგორც Apple Contact აპში:
მე ვცადე შემდეგის დამატება სხვადასხვა ადგილებში, მაგრამ ეს შედეგს არ იძლევა:
headerLargeTitle: true,
headerSearchBarOptions: {
placeholder: 'Search'
}
დოკუმენტაცია საკმაოდ მსუბუქია, და მაგალითები მოძველებულია ან არ იყენებს ფაილზე დაფუძნებულ Expo Router v3-ს. იგი დაშორდა React Navigation-ს, ამიტომ იქ არსებული დოკუმენტაცია არ შეესაბამება Expo Router-ის გამოყენებას. ჩემი სტრუქტურა სწორია თუ რა არასწორად გავაკეთე? ნებისმიერი დახმარება ან რჩევა ფასეული იქნება!
პასუხი #1
@TruMan1-ის წინადადება მართალია. ეს ჩემს შემთხვევაში მუშაობდა. აი, მაგალითი იმპლემენტაციისა, რომელიც Expo-ს ფაილზე დაფუძნებული როუტინგის გამოყენებით გაკეთდა.
ფოლდერის სტრუქტურა
app
├── (tabs)
│ ├── _layout.tsx
│ ├── index
│ │ ├── _layout.tsx
│ │ └── index.tsx
│ └── settings
│ ├── _layout.tsx
│ └── index.tsx
├── +not-found.tsx
└── _layout.tsx
ფაილები
app/_layout.tsxexport default function RootLayout() {
return (
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
);
}
app/(tabs)/_layout.tsxexport default function TabLayout() {
return (
<Tabs
screenOptions={{
headerShown: false,
tabBarStyle: { position: "absolute", elevation: 0 },
tabBarBackground: () => (
<BlurView
intensity={80}
tint={"prominent"}
style={StyleSheet.absoluteFill}
/>
),
}}
>
<Tabs.Screen name="index" options={{ title: "Home" }} />
<Tabs.Screen name="settings" options={{ title: "Settings" }} />
</Tabs>
);
}
app/(tabs)/index/_layout.tsxexport default function HomeLayout() {
return (
<Stack>
<Stack.Screen
name="index"
options={{
headerShown: true,
headerLargeTitle: true,
headerTitle: "Home",
}}
/>
</Stack>
);
}
app/(tabs)/index/index.tsximport { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
export default function HomeScreen({ children }: Props) {
const bottomTabHeight = useBottomTabBarHeight();
return (
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View style={{ paddingBottom: bottomTabHeight }}>{children}</View>
</ScrollView>
);
}
app/(tabs)/settings/_layout.tsxexport default function SettingsLayout() {
return (
<Stack>
<Stack.Screen
name="index"
options={{
headerShown: true,
headerLargeTitle: true,
headerTitle: "Settings",
}}
/>
</Stack>
);
}
app/(tabs)/settings/index.tsximport { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
export default function SettingsScreen({ children }: Props) {
const bottomTabHeight = useBottomTabBarHeight();
return (
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View style={{ paddingBottom: bottomTabHeight }}>{children}</View>
</ScrollView>
);
}
პასუხი #2
Expo როუტერი თითქოს შეზღუდულია, რადგან ახალია - მინიმუმ, დოკუმენტაცია მასზე არასრულია. იმისთვის, რომ სწორად აკეთოთ ის, რასაც ცდილობთ, საჭიროა შეცვალოთ სტრუქტურა ისე, რომ სტეკები ტაბში იყოს ტაბის ნაცვლად, რომელიც სტეკშია:
<SafeAreaProvider>
<NavigationContainer>
<Tab.Navigator
screenOptions={{
headerShown: false,
...(Platform.OS === 'ios'
? {
tabBarStyle: { position: 'absolute', elevation: 0 },
tabBarBackground: () => (
<BlurView tint="prominent" intensity={100} style={StyleSheet.absoluteFill} />
)
}
: undefined)
}}
>
<Tab.Screen name="HomeTab" component={HomeStack} />
<Tab.Screen name="SettingsTab" component={SettingsStack} />
<Tab.Screen name="MoreTab" component={MoreStack} />
</Tab.Navigator>
</NavigationContainer>
</SafeAreaProvider>
const Stack = createNativeStackNavigator();
export function Home({ navigation }: NativeStackScreenProps<ParamListBase>) {
const data = Array.from({ length: 50 });
useLayoutEffect(() => {
navigation.setOptions({
headerSearchBarOptions: {
onChangeText: (text) => console.log(text)
}
});
}, [navigation]);
return (
<View style={{ flex: 1, backgroundColor: 'yellow' }}>
<Text>Home screen</Text>
<Button title="Go to Details" onPress={() => navigation.navigate('Details')} />
{data.map((_, index) => (
<Text key={index} style={{ padding: 10, fontSize: 18, fontWeight: 'bold', color: 'blue' }}>
Item {index + 1}
</Text>
))}
</View>
);
}
export function HomeStack() {
return (
<Stack.Navigator
screenOptions={{
headerTransparent: Platform.OS === 'ios',
headerBlurEffect: 'systemThickMaterial'
}}
>
<Stack.Screen name="Home" component={withScrollStackView(Home)} options={{ headerLargeTitle: true }} />
<Stack.Screen name="Details" component={withScrollStackView(Details)} />
</Stack.Navigator>
);
}
export default function Details() {
return (
<View style={{ flex: 1, backgroundColor: 'yellow' }}>
<Text>Details screen</Text>
</View>
);
}
მეტი დეტალები შეგიძლიათ პირდაპირ იხილოთ React Navigation დოკუმენტაციაში, რომელიც Expo Router-ის ნაწილია: https://reactnavigation.org/docs/tab-based-navigation#a-stack-navigator-for-each-tab


