feat: 支持 glass

This commit is contained in:
2025-09-11 23:25:56 +08:00
parent dfe9506a7a
commit 1af0945a2f
4 changed files with 57 additions and 3 deletions

View File

@@ -1,4 +1,5 @@
import type { BottomTabNavigationOptions } from '@react-navigation/bottom-tabs'; import type { BottomTabNavigationOptions } from '@react-navigation/bottom-tabs';
import { GlassContainer, GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
import * as Haptics from 'expo-haptics'; import * as Haptics from 'expo-haptics';
import { Tabs, usePathname } from 'expo-router'; import { Tabs, usePathname } from 'expo-router';
import React from 'react'; import React from 'react';
@@ -27,6 +28,7 @@ export default function TabLayout() {
const theme = (useColorScheme() ?? 'light') as 'light' | 'dark'; const theme = (useColorScheme() ?? 'light') as 'light' | 'dark';
const colorTokens = Colors[theme]; const colorTokens = Colors[theme];
const pathname = usePathname(); const pathname = usePathname();
const glassEffectAvailable = isLiquidGlassAvailable();
// Helper function to determine if a tab is selected // Helper function to determine if a tab is selected
const isTabSelected = (routeName: string): boolean => { const isTabSelected = (routeName: string): boolean => {
@@ -96,20 +98,51 @@ export default function TabLayout() {
); );
}; };
// Custom tab bar background component
const TabBarBackground = () => {
if (glassEffectAvailable) {
return (
<GlassContainer
spacing={8}
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
borderRadius: 34,
}}
>
<GlassView
isInteractive
glassEffectStyle="regular"
tintColor={theme === 'dark' ? 'rgba(0,0,0,0.3)' : 'rgba(255,255,255,0.3)'}
style={{
flex: 1,
borderRadius: 34,
}}
/>
</GlassContainer>
);
}
return null;
};
// Common screen options // Common screen options
const getScreenOptions = (routeName: string): BottomTabNavigationOptions => ({ const getScreenOptions = (routeName: string): BottomTabNavigationOptions => ({
headerShown: false, headerShown: false,
tabBarActiveTintColor: colorTokens.tabIconSelected, tabBarActiveTintColor: colorTokens.tabIconSelected,
tabBarButton: createTabButton(routeName), tabBarButton: createTabButton(routeName),
tabBarBackground: TabBarBackground,
tabBarStyle: { tabBarStyle: {
position: 'absolute', position: 'absolute',
bottom: TAB_BAR_BOTTOM_OFFSET, bottom: TAB_BAR_BOTTOM_OFFSET,
height: TAB_BAR_HEIGHT, height: TAB_BAR_HEIGHT,
borderRadius: 34, borderRadius: 34,
backgroundColor: colorTokens.tabBarBackground, backgroundColor: glassEffectAvailable ? 'transparent' : colorTokens.tabBarBackground,
shadowColor: '#000', shadowColor: '#000',
shadowOffset: { width: 0, height: 2 }, shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2, shadowOpacity: glassEffectAvailable ? 0.1 : 0.2,
shadowRadius: 10, shadowRadius: 10,
elevation: 5, elevation: 5,
paddingHorizontal: 10, paddingHorizontal: 10,
@@ -119,6 +152,8 @@ export default function TabLayout() {
left: 20, left: 20,
right: 20, right: 20,
alignSelf: 'center', alignSelf: 'center',
borderWidth: glassEffectAvailable ? 1 : 0,
borderColor: glassEffectAvailable ? (theme === 'dark' ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)') : 'transparent',
} as ViewStyle, } as ViewStyle,
tabBarItemStyle: { tabBarItemStyle: {
backgroundColor: 'transparent', backgroundColor: 'transparent',

View File

@@ -57,6 +57,8 @@ PODS:
- ExpoModulesCore - ExpoModulesCore
- ExpoFont (14.0.7): - ExpoFont (14.0.7):
- ExpoModulesCore - ExpoModulesCore
- ExpoGlassEffect (0.1.1):
- ExpoModulesCore
- ExpoHaptics (15.0.6): - ExpoHaptics (15.0.6):
- ExpoModulesCore - ExpoModulesCore
- ExpoHead (6.0.0): - ExpoHead (6.0.0):
@@ -3052,6 +3054,7 @@ DEPENDENCIES:
- ExpoCamera (from `../node_modules/expo-camera/ios`) - ExpoCamera (from `../node_modules/expo-camera/ios`)
- ExpoFileSystem (from `../node_modules/expo-file-system/ios`) - ExpoFileSystem (from `../node_modules/expo-file-system/ios`)
- ExpoFont (from `../node_modules/expo-font/ios`) - ExpoFont (from `../node_modules/expo-font/ios`)
- ExpoGlassEffect (from `../node_modules/expo-glass-effect/ios`)
- ExpoHaptics (from `../node_modules/expo-haptics/ios`) - ExpoHaptics (from `../node_modules/expo-haptics/ios`)
- ExpoHead (from `../node_modules/expo-router/ios`) - ExpoHead (from `../node_modules/expo-router/ios`)
- ExpoImage (from `../node_modules/expo-image/ios`) - ExpoImage (from `../node_modules/expo-image/ios`)
@@ -3203,6 +3206,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/expo-file-system/ios" :path: "../node_modules/expo-file-system/ios"
ExpoFont: ExpoFont:
:path: "../node_modules/expo-font/ios" :path: "../node_modules/expo-font/ios"
ExpoGlassEffect:
:path: "../node_modules/expo-glass-effect/ios"
ExpoHaptics: ExpoHaptics:
:path: "../node_modules/expo-haptics/ios" :path: "../node_modules/expo-haptics/ios"
ExpoHead: ExpoHead:
@@ -3426,6 +3431,7 @@ SPEC CHECKSUMS:
ExpoCamera: ae1d6691b05b753261a845536d2b19a9788a8750 ExpoCamera: ae1d6691b05b753261a845536d2b19a9788a8750
ExpoFileSystem: 7b4a4f6c67a738e826fd816139bac9d098b3b084 ExpoFileSystem: 7b4a4f6c67a738e826fd816139bac9d098b3b084
ExpoFont: 74a14c605637c2d32337a2f542065408a8ca3454 ExpoFont: 74a14c605637c2d32337a2f542065408a8ca3454
ExpoGlassEffect: 9aa58a46e8abe720971f2b588bc1e10d58728ba8
ExpoHaptics: e0912a9cf05ba958eefdc595f1990b8f89aa1f3f ExpoHaptics: e0912a9cf05ba958eefdc595f1990b8f89aa1f3f
ExpoHead: 275ef6292a9ab92669fd9554f19e1b1bbb5aa986 ExpoHead: 275ef6292a9ab92669fd9554f19e1b1bbb5aa986
ExpoImage: 18d9836939f8e271364a5a2a3566f099ea73b2e4 ExpoImage: 18d9836939f8e271364a5a2a3566f099ea73b2e4

12
package-lock.json generated
View File

@@ -30,6 +30,7 @@
"expo-camera": "~17.0.7", "expo-camera": "~17.0.7",
"expo-constants": "~18.0.8", "expo-constants": "~18.0.8",
"expo-font": "~14.0.7", "expo-font": "~14.0.7",
"expo-glass-effect": "^0.1.1",
"expo-haptics": "~15.0.6", "expo-haptics": "~15.0.6",
"expo-image": "~3.0.7", "expo-image": "~3.0.7",
"expo-image-picker": "~17.0.7", "expo-image-picker": "~17.0.7",
@@ -7910,6 +7911,17 @@
"react-native": "*" "react-native": "*"
} }
}, },
"node_modules/expo-glass-effect": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/expo-glass-effect/-/expo-glass-effect-0.1.1.tgz",
"integrity": "sha512-81xXB2CVjgyg7gaq/fDVAOu/j43uTP0F6bI0sah81v3/guA+YfSM3QjyfegIVQPUkX/9AP2zkU9ihkHEZQv7pg==",
"license": "MIT",
"peerDependencies": {
"expo": "*",
"react": "*",
"react-native": "*"
}
},
"node_modules/expo-haptics": { "node_modules/expo-haptics": {
"version": "15.0.6", "version": "15.0.6",
"resolved": "https://registry.npmjs.org/expo-haptics/-/expo-haptics-15.0.6.tgz", "resolved": "https://registry.npmjs.org/expo-haptics/-/expo-haptics-15.0.6.tgz",

View File

@@ -34,6 +34,7 @@
"expo-camera": "~17.0.7", "expo-camera": "~17.0.7",
"expo-constants": "~18.0.8", "expo-constants": "~18.0.8",
"expo-font": "~14.0.7", "expo-font": "~14.0.7",
"expo-glass-effect": "^0.1.1",
"expo-haptics": "~15.0.6", "expo-haptics": "~15.0.6",
"expo-image": "~3.0.7", "expo-image": "~3.0.7",
"expo-image-picker": "~17.0.7", "expo-image-picker": "~17.0.7",
@@ -80,4 +81,4 @@
"typescript": "~5.9.2" "typescript": "~5.9.2"
}, },
"private": true "private": true
} }