Mit iOS 26 hat Apple Liquid Glass eingeführt — ein dynamischer Glasmorphism-Effekt, der sich in Echtzeit an den Hintergrund anpasst. Für React Native Entwickler stellt sich die Frage: Wie nutze ich das in meiner Expo-App? In diesem Guide zeige ich dir die komplette Implementierung mit Expo SDK 55, inklusive einem 3-Tier-Fallback-System für ältere iOS-Versionen und Android.
Voraussetzungen
Expo SDK 55 bringt alles mit, was du brauchst: expo-glass-effect für die native Liquid Glass Komponente (GlassView), expo-blur als Fallback für ältere iOS-Versionen, expo-symbols für SF Symbols Icons, und expo-router mit nativer Liquid Glass Integration.
Schritt 1: Platform Detection
Der wichtigste Baustein: Eine Utility-Funktion, die erkennt, ob Liquid Glass verfügbar ist. Diese Funktion ist die Basis für das gesamte Fallback-System.
import { Platform } from 'react-native';export function isIOS26OrLater(): boolean { if (Platform.OS !== 'ios') return false; return parseInt(Platform.Version as string, 10) >= 26;}Schritt 2: Das 3-Tier-Fallback-System
Tier 1 (iOS 26+): Natives Liquid Glass via GlassView. Tier 2 (iOS < 26): BlurView mit systemChromeMaterial. Tier 3 (Android): Opaker Fallback mit Background-Color. Dieses System stellt sicher, dass deine App auf jedem Gerät gut aussieht.
Schritt 3: GlassCard — Container mit Glaseffekt
Die GlassCard ist die Basis-Komponente für alle glasartigen Container. Wichtig: overflow: 'hidden' ist Pflicht — ohne das rendert der Effekt über die Grenzen der Komponente hinaus. Bei BlurView muss der Content zIndex: 1 haben, damit er über dem Blur-Layer erscheint.
import { GlassView } from 'expo-glass-effect';import { BlurView } from 'expo-blur';import { Platform, StyleSheet, View } from 'react-native';import { isIOS26OrLater } from '@/utils/platform';export function GlassCard({ children, style, tintColor }) { // Tier 1: iOS 26+ — native Liquid Glass if (isIOS26OrLater()) { return ( <GlassView glassEffectStyle="regular" tintColor={tintColor} style={[styles.card, style]}> {children} </GlassView> ); } // Tier 2: iOS < 26 — BlurView if (Platform.OS === 'ios') { return ( <View style={[styles.card, style]}> <BlurView tint="systemChromeMaterial" intensity={80} style={StyleSheet.absoluteFill} /> <View style={{ zIndex: 1 }}>{children}</View> </View> ); } // Tier 3: Android — opaque fallback return ( <View style={[styles.card, { backgroundColor: '#1a1a1a' }, style]}> {children} </View> );}const styles = StyleSheet.create({ card: { borderRadius: 20, padding: 16, overflow: 'hidden', },});Schritt 4: GlassIconButton — Interaktive Glass-Buttons
Auf iOS 26+ übernimmt isInteractive die native Bounce-Animation. Für ältere Versionen baust du sie mit Reanimated nach.
import { GlassView } from 'expo-glass-effect';import { SymbolView } from 'expo-symbols';import { Pressable, StyleSheet, View } from 'react-native';import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing} from 'react-native-reanimated';import { isIOS26OrLater } from '@/utils/platform';const AnimatedPressable = Animated.createAnimatedComponent(Pressable);export function GlassIconButton({ name, onPress, size = 20 }) { const scale = useSharedValue(1); const animatedStyle = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }], })); const handlePressIn = () => { scale.value = withTiming(0.82, { duration: 120, easing: Easing.out(Easing.ease), }); }; const handlePressOut = () => { scale.value = withTiming(1, { duration: 200, easing: Easing.out(Easing.back(1.5)), }); }; const icon = ( <SymbolView name={name} tintColor="#fff" size={size} weight="semibold" /> ); // iOS 26+: isInteractive handles the bounce if (isIOS26OrLater()) { return ( <Pressable onPress={onPress}> <GlassView glassEffectStyle="regular" isInteractive style={styles.button}> {icon} </GlassView> </Pressable> ); } // Fallback: Reanimated scale animation return ( <AnimatedPressable onPressIn={handlePressIn} onPressOut={handlePressOut} onPress={onPress} style={animatedStyle}> <View style={[styles.button, { backgroundColor: 'rgba(255,255,255,0.1)' }]}> {icon} </View> </AnimatedPressable> );}const styles = StyleSheet.create({ button: { width: 44, height: 44, borderRadius: 999, alignItems: 'center', justifyContent: 'center', overflow: 'hidden', },});Schritt 5: Header-Toolbar mit Glass-Buttons
Expo-router bietet unstable_headerRightItems und unstable_headerLeftItems für custom Header-Items. Setze headerBlurEffect auf undefined auf iOS 26+, damit natives Liquid Glass den Effekt übernimmt. hidesSharedBackground: true verhindert doppelte Glass-Hintergründe.
import { Stack } from 'expo-router';import { Platform } from 'react-native';import { GlassIconButton } from '@/components/ui/glass-icon-button';import { isIOS26OrLater } from '@/utils/platform';export default function HomeLayout() { return ( <Stack> <Stack.Screen name="index" options={{ title: 'Übersicht', headerTransparent: Platform.OS === 'ios', headerBlurEffect: isIOS26OrLater() ? undefined : 'dark', unstable_headerRightItems: () => [{ type: 'custom', element: ( <GlassIconButton name="bell.fill" onPress={() => router.push('/notifications')} /> ), hidesSharedBackground: true, }], unstable_headerLeftItems: () => [{ type: 'custom', element: ( <GlassIconButton name="gearshape.fill" onPress={() => router.push('/settings')} /> ), hidesSharedBackground: true, }], }} /> </Stack> );}Schritt 6: Tab Bar mit NativeTabs
Die Tab Bar bekommt Liquid Glass automatisch mit NativeTabs. Auf iOS 26+ rendert NativeTabs automatisch eine Tab Bar mit Liquid Glass Effekt — kein zusätzlicher Code nötig.
import { NativeTabs } from 'expo-router/unstable-native-tabs';export default function AppTabs() { return ( <NativeTabs labelVisibilityMode="unlabeled" iconColor={{ selected: '#EA580C' }}> <NativeTabs.Trigger name="home"> <NativeTabs.Trigger.Label hidden /> <NativeTabs.Trigger.Icon sf={{ default: 'house', selected: 'house.fill' }} /> </NativeTabs.Trigger> <NativeTabs.Trigger name="explore"> <NativeTabs.Trigger.Label hidden /> <NativeTabs.Trigger.Icon sf={{ default: 'safari', selected: 'safari.fill' }} /> </NativeTabs.Trigger> <NativeTabs.Trigger name="profile" role="search"> <NativeTabs.Trigger.Icon sf={{ default: 'person', selected: 'person.fill' }} /> </NativeTabs.Trigger> </NativeTabs> );}Schritt 7: Farbiges Liquid Glass
Für einen Highlight-Button mit farbigem Glass-Effekt: tintColor mit reduzierter Opacity (BF = 75% als Hex-Suffix) gibt einen subtilen Farbton, ohne die Transparenz zu zerstören.
<Pressable onPress={handleAction}> {isIOS26OrLater() ? ( <GlassView glassEffectStyle="regular" isInteractive tintColor={`${accentColor}BF`} style={styles.ctaButton}> <SymbolView name="sparkles" size={18} tintColor="#fff" weight="semibold" /> <Text style={styles.label}>Jetzt starten</Text> </GlassView> ) : ( <View style={[styles.ctaButton, styles.fallback]}> <BlurView tint="dark" intensity={60} style={StyleSheet.absoluteFill} /> <View style={{ zIndex: 1, flexDirection: 'row', alignItems: 'center', gap: 8 }}> <SymbolView name="sparkles" size={18} tintColor="#fff" weight="semibold" /> <Text style={styles.label}>Jetzt starten</Text> </View> </View> )}</Pressable>Schritt 8: Stack-Screens konfigurieren
Für jeden Stack-Screen das gleiche Pattern — egal ob Settings, Detail-Ansicht oder Modal.
<Stack.Screen name="settings" options={{ title: 'Einstellungen', presentation: 'card', headerBackTitle: 'Zurück', headerTransparent: Platform.OS === 'ios', headerBlurEffect: isIOS26OrLater() ? undefined : 'regular', }}/>Die wichtigsten Regeln
1. Immer overflow: 'hidden' — ohne das rendert GlassView über die Komponentengrenzen hinaus. 2. isInteractive nur für klickbare Elemente. 3. headerBlurEffect: undefined auf iOS 26+ — sonst kollidiert Legacy-Blur mit Liquid Glass. 4. hidesSharedBackground: true — verhindert doppelte Glass-Hintergründe bei custom Header-Items. 5. zIndex: 1 über BlurView — Content verschwindet sonst hinter dem Blur-Layer. 6. Alle drei Tiers implementieren — nicht jeder User hat iOS 26.
Fazit
Liquid Glass in React Native mit Expo SDK 55 ist überraschend einfach — wenn du das Pattern einmal verstanden hast. Bau dir eine GlassCard und einen GlassIconButton als Basis-Komponenten, und du kannst Liquid Glass konsistent durch deine gesamte App einsetzen. Der Effekt ist subtil, aber er macht einen spürbaren Unterschied — deine App fühlt sich sofort wie eine native iOS 26 App an.