expo-liquid-glass-native
v1.3.16
Published
Expo module for LiquidGlass native Android components with beautiful glassmorphism effects
Maintainers
Readme
expo-liquid-glass-native
Expo module for LiquidGlass native Android components with beautiful glassmorphism effects.
Note: This library is an Expo adaptation of AndroidLiquidGlass by Kyant0. It provides native Android components with liquid glass effects for React Native/Expo applications. iOS support is planned for future releases.
In the current implementation, ExpoLiquidGlassNativeView is the primary component, and LiquidButtonView is a backward-compatible alias for the same underlying view.
Demo
Installation
Step 1: Install the package
npm install expo-liquid-glass-nativeor
yarn add expo-liquid-glass-nativeStep 2: Add plugin to app.json
Add the plugin to your app.json (or app.config.js):
{
"expo": {
"plugins": [
"expo-liquid-glass-native"
]
}
}Step 3: Prebuild native code
Run prebuild to generate native code with the plugin applied:
npx expo prebuild --cleanNote: If you're using Expo Development Build, the prebuild will happen automatically when you run:
npx expo run:androidThat's it! The config plugin will automatically:
- ✅ Add Compose plugin to
settings.gradle - ✅ Add Compose dependencies to
app/build.gradle - ✅ Add Kotlin JVM toolchain configuration for Java 17
No manual native code configuration needed! 🎉
Usage
ExpoLiquidGlassNativeView
For new code, prefer using ExpoLiquidGlassNativeView directly. It renders the glass surface natively and places React Native children as overlay content above it. useRealtimeCapture is enabled by default.
Current default preset:
tint="#FFFFFF"blurRadius={4}lensX={50}lensY={50}cornerRadius={28}useRealtimeCapture={true}
surfaceColor is optional. Add it only if you want an extra translucent surface layer on top of the tint-driven glass.
The example below shows the default preset and an explicit optional surfaceColor:
import { ExpoLiquidGlassNativeView } from 'expo-liquid-glass-native';
import { Text, View } from 'react-native';
function MyGlassCard() {
return (
<ExpoLiquidGlassNativeView
tint="#FFFFFF"
surfaceColor="#14FFFFFF"
blurRadius={4}
lensX={50}
lensY={50}
cornerRadius={28}
useRealtimeCapture={true}
style={{ width: 240, padding: 20, borderRadius: 28 }}
>
<View>
<Text style={{ fontSize: 18, fontWeight: '600' }}>Liquid Glass</Text>
<Text style={{ marginTop: 6 }}>Overlay content rendered above the blur.</Text>
</View>
</ExpoLiquidGlassNativeView>
);
}Props:
tint?: string- Tint color in hex format. Default:"#FFFFFF"surfaceColor?: string- Optional surface color in hex format with alpha. Omit it to render only the tint-driven glass layer.blurRadius?: number- Blur radius in dp. Default:4lensX?: number- Lens X radius in dp. Default:50lensY?: number- Lens Y radius in dp. Default:50cornerRadius?: number- Corner radius in dp. Default:28imageUri?: string- URI of the background image (deprecated, usebackgroundImageUriinstead)backgroundImageUri?: string- URI of the background image for this specific buttonuseRealtimeCapture?: boolean- Use realtime screen capture instead of image. Captures the entire screen behind the component. Default:truerenderBackgroundContent?: boolean- Render background content in Compose (default: false)children?: React.ReactNode- Overlay content rendered above the native glass surfacestyle?: ViewStyle- Style object
Alias: LiquidButtonView is a backward-compatible alias of ExpoLiquidGlassNativeView.
Note: When useRealtimeCapture is enabled, the component captures the screen content behind it in real time. Overlay children are excluded from the blurred backdrop so foreground content stays sharp.
Experimental Android realtime overlay path: On Android, the realtime capture path currently renders visible overlay content through a separate overlay root/window so the backdrop can be captured without including the component itself or its children. This improves backdrop fidelity, but it also means overlay children do not behave exactly like normal inline React Native descendants in every case. Test touch handling, accessibility, clipping, stacking, and context-sensitive UI carefully before shipping to production.
BottomTabs
import { BottomTabsContentView } from 'expo-liquid-glass-native';
import { Image } from 'react-native';
import { useState, useMemo } from 'react';
function MyTabs() {
const [selectedTab, setSelectedTab] = useState(0);
// Convert require() images to URIs
const tabIcons = useMemo(() => {
const icons = [
require('./assets/home.png'),
require('./assets/search.png'),
require('./assets/profile.png'),
];
return icons.map(icon => {
try {
const source = Image.resolveAssetSource(icon);
return source?.uri || null;
} catch (e) {
console.warn('Failed to resolve asset source:', e);
return null;
}
}).filter(Boolean);
}, []);
return (
<BottomTabsContentView
selectedTabIndex={selectedTab}
tabsCount={3}
tabLabels={['Home', 'Search', 'Profile']}
tabIcons={tabIcons}
iconTintEnabled={true}
onTabSelected={(event) => {
setSelectedTab(event.nativeEvent.index);
console.log('Tab selected:', event.nativeEvent.index);
}}
style={{ flex: 1 }}
/>
);
}Props:
selectedTabIndex?: number- Currently selected tab index (default: 0)tabsCount?: number- Number of tabs (default: 3)tabLabels?: string[]- Array of tab labelstabIcons?: string[]- Array of icon URIs (useImage.resolveAssetSource()to convert require() images to URIs)iconTintEnabled?: boolean- Whether to apply content color tint to icons (default: true)onTabSelected?: (event: { nativeEvent: { index: number } }) => void- Tab selection handlerstyle?: ViewStyle- Style object
Note: tabIcons should be an array of URI strings. Use Image.resolveAssetSource() to convert require() images to URIs.
Features
- ✨ Beautiful Glassmorphism Effects - Native Android components with liquid glass effects
- 🎨 Realtime Background Capture - Capture screen content behind the component in real time
- 🧩 Overlay Children Support - Render React Native children above the native glass layer
- 📱 ScrollView Compatible - Works with ScrollViews and other scrollable containers
- 🎯 Customizable - Adjust blur radius, lens size, colors, and more
- 🚀 Performance Optimized - Hardware-accelerated rendering with efficient caching
Requirements
- Android: minSdkVersion 24
- iOS: Not yet implemented (PRs welcome!)
- Expo SDK: 54+
Examples
Check out the example directory for complete usage examples, including:
- Basic button usage
- Buttons with realtime background capture
- Bottom tabs navigation
- ScrollView integration
Performance Tips
- Realtime Capture: Use
useRealtimeCapturesparingly. Consider using staticbackgroundImageUriwhen possible. - Blur Radius: Lower blur radius values perform better than higher values.
- Caching: The library automatically caches captured bitmaps for better performance.
Known Limitations
- iOS support is planned for future releases
- Realtime capture may have slight performance impact on lower-end devices
- Some complex Android view hierarchies may not capture exactly as expected
- The Android realtime overlay path is currently experimental and may differ from standard inline
childrenbehavior in some edge cases
License
See LICENSE for details.
Contributing
PRs are welcome! Please open an issue first to discuss major changes before submitting a pull request.
