Implementing Advanced UI Patterns
1. Creating Bottom Sheets
| Property | Description | Default |
|---|---|---|
| visible | Controls visibility of the bottom sheet | false |
| onDismiss | Callback when the bottom sheet is dismissed | () => {} |
| snapPoints | Array of snap points for the bottom sheet (e.g., [0, 50, 100]) | [100] |
| sheetStyle | Custom styles for the bottom sheet container | {} |
Example: Basic Bottom Sheet Implementation
import React, { useState } from 'react';
import { BottomSheet } from 'react-native-bottom-sheet';
const MyBottomSheet = () => {
const [visible, setVisible] = useState(false);
return (
<BottomSheet
visible={visible}
onDismiss={() => setVisible(false)}
snapPoints={[0, 50, 100]}
>
<View style={{ padding: 20 }}>
<Text>Bottom Sheet Content</Text>
</View>
</BottomSheet>
);
};
Note: The
snapPoints array defines how the bottom sheet can be positioned. Values are in percentage of screen height.
2. Implementing Skeleton Screens
Skeleton screens are a UI pattern that displays placeholder content while data is loading, improving perceived performance and user experience.
| Property | Description | Usage |
|---|---|---|
| SkeletonScreen | Component that renders skeleton placeholders | <SkeletonScreen /> |
| SkeletonContent | Container for skeleton elements | <SkeletonContent /> |
| SkeletonItem | Individual skeleton element (e.g., text, image) | <SkeletonItem /> |
Example: Basic Skeleton Screen
<View style={styles.container}>
<SkeletonContent
layout={[
{ type: 'rect', width: 200, height: 20 },
{ type: 'rect', width: 200, height: 20, marginTop: 10 },
{ type: 'rect', width: 200, height: 20, marginTop: 10 },
]}
isLoading={isLoading}
/>
</View>
Example: Skeleton with Image
<View style={styles.container}>
<SkeletonContent
layout={[
{ type: 'image', width: 100, height: 100 },
{ type: 'rect', width: 200, height: 20, marginTop: 10 },
{ type: 'rect', width: 200, height: 20, marginTop: 10 },
]}
isLoading={isLoading}
/>
</View>
Note: Use
SkeletonContent to define the layout and isLoading prop to control visibility.
Warning: Ensure skeleton elements match the actual content dimensions to avoid layout shifts.
3. Creating Carousels and Sliders
Example: Basic Carousel with ScrollView
<ScrollView
horizontal
pagingEnabled
showsHorizontalScrollIndicator={false}
>
<View style={{ width: screenWidth }}>
<Image source={require("./image1.jpg")} style={{ width: screenWidth, height: 200 }} />
</View>
<View style={{ width: screenWidth }}>
<Image source={require("./image2.jpg")} style={{ width: screenWidth, height: 200 }} />
</View>
<View style={{ width: screenWidth }}>
<Image source={require("./image3.jpg")} style={{ width: screenWidth, height: 200 }} />
</View>
</ScrollView>
| Property | Description | Default |
|---|---|---|
| horizontal | Scrolls horizontally instead of vertically | false |
| pagingEnabled | Snaps to full screen pages | false |
| showsHorizontalScrollIndicator | Whether to show horizontal scroll indicator | true |
Note: For better performance with many items, consider using
FlatList with horizontal layout.
Example: Slider with PanGestureHandler
import { PanGestureHandler } from "react-native-gesture-handler";
const Slider = () => {
const pan = usePanGestureHandler();
const translateX = new Animated.Value(0);
return (
<PanGestureHandler onGestureEvent={pan}>
<Animated.View
style={[
{ width: 100, height: 20 },
{ transform: [{ translateX }] }
]}
>
<View style={{ backgroundColor: "blue", width: "100%", height: "100%" }} />
</Animated.View>
</PanGestureHandler>
);
};
| Property | Description | Notes |
|---|---|---|
| onGestureEvent | Callback for gesture events | Required for interaction |
| activeState | Current state of the gesture | Can be used to control animation |
4. Implementing Accordions
| Property | Description | Default |
|---|---|---|
| expanded | Controls whether the accordion is expanded or collapsed | false |
| onChange | Callback function when accordion state changes | () => {} |
| title | Text to display as the accordion header | '' |
Example: Basic Accordion Component
import React, { useState } from 'react';\nimport { View, Text, TouchableOpacity, StyleSheet } from 'react-native';\n\nconst Accordion = ({ title, children }) => {\n const [expanded, setExpanded] = useState(false);\n\n return (\n <View style={styles.container}>\n <TouchableOpacity\n style={styles.header}\n onPress={() => setExpanded(!expanded)}\n >\n <Text style={styles.title}>{title}</Text>\n <Text>{expanded ? '−' : '+'}</Text>\n </TouchableOpacity>\n {expanded && <View style={styles.content}>{children}</View>}\n </View>\n );\n};\n\nconst App = () => {\n return (\n <View style={styles.main}>\n <Accordion title="Section 1">\n <Text>Content for section 1</Text>\n </Accordion>\n <Accordion title="Section 2">\n <Text>Content for section 2</Text>\n </Accordion>\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: {\n borderWidth: 1,\n borderColor: '#ccc',\n borderRadius: 4,\n marginBottom: 10,\n },\n header: {\n padding: 15,\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n title: {\n fontSize: 16,\n fontWeight: 'bold',\n },\n content: {\n padding: 15,\n },\n main: {\n padding: 20,\n },\n});\n\nexport default App;
Note: The Accordion component uses
useState to manage the expanded/collapsed state and toggles visibility of content based on that state.
5. Creating Custom Modals
| Property | Description | Default |
|---|---|---|
| visible | Controls the visibility of the modal | false |
| animationType | Defines the animation style when showing/hiding the modal | none |
| transparent | Makes the modal background transparent | false |
| hardwareAccelerated | Enables hardware acceleration for smoother animations | false |
Example: Basic Custom Modal
import React, { useState } from 'react';
import { Modal, View, Text, TouchableOpacity } from 'react-native';
const CustomModal = () => {
const [modalVisible, setModalVisible] = useState(false);
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity onPress={() => setModalVisible(true)}>
<Text>Open Modal</Text>
</TouchableOpacity>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => setModalVisible(false)}
>
<View style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)'
}}>
<View style={{
backgroundColor: 'white',
padding: 20,
borderRadius: 10
}}>
<Text>Hello from Modal!</Text>
<TouchableOpacity onPress={() => setModalVisible(false)}>
<Text>Close</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</View>
);
};
export default CustomModal;
Note: The
transparent property allows the modal to show content behind it, useful for overlay effects.
Warning: Make sure to handle the
onRequestClose event for better accessibility and user experience on Android.
Key Points
- Use
Modalcomponent for custom modal UIs in React Native - Set
animationTypetoslide,fade, ornone - Control visibility with the
visibleprop - Use
transparentfor overlay effects
6. Implementing Sticky Headers
| Property | Description | Usage |
|---|---|---|
| stickyHeaderIndices | Array of indices for headers that should stick to the top | stickyHeaderIndices={[0, 2]} |
| SectionList | Component to use for sticky headers in lists | SectionList with stickyHeaderIndices |
Example: Sticky Header in SectionList
import React from 'react';
import { SectionList, Text, View } from 'react-native';
const data = [
{
title: 'Section A',
data: ['Item 1', 'Item 2']
},
{
title: 'Section B',
data: ['Item 3', 'Item 4']
}
];
const StickyHeaderExample = () => {
return (
<SectionList
sections={data}
stickyHeaderIndices={[0, 1]}
renderItem={({ item }) => <Text>{item}</Text>}
renderSectionHeader={({ section }) => (
<View style={{ backgroundColor: '#f0f0f0' }}>
<Text>{section.title}</Text>
</View>
)}
/>
);
};
export default StickyHeaderExample;
Note:
stickyHeaderIndices must be an array of numbers indicating the indices of sections that should stick.
Warning: Sticky headers may not work as expected in all list components. Use
SectionList for best results.
7. Creating Floating Action Buttons
| Property | Description | Default |
|---|---|---|
| position | Position of the FAB relative to the screen edges | 'bottom-right' |
| size | Size of the FAB button | 'normal' |
| icon | Icon to display inside the FAB | 'add' |
| color | Background color of the FAB | '#1976D2' |
Example: Basic Floating Action Button
import { Fab } from 'react-native-paper';
<Fab
icon="plus"
onPress={() => console.log('Pressed')}
style={{ position: 'absolute', bottom: 16, right: 16 }}
/>
Example: Custom Styled FAB
import { Fab } from 'react-native-paper';
<Fab
icon="edit"
color="#FF5722"
size="small"
style={{ position: 'absolute', bottom: 16, left: 16 }}
/>
Note: The FAB component requires
react-native-paper to be installed and properly configured in your project.
8. Implementing Collapsible Headers
| Property | Description | Default |
|---|---|---|
| collapsible | Enables or disables the collapsible behavior of the header | false |
| collapsedHeight | Height of the header when collapsed | 50 |
| expandedHeight | Height of the header when expanded | 100 |
| scrollOffset | Scroll offset to trigger header collapse | 100 |
Example: Collapsible Header Implementation
import React, { useState } from 'react';<br />import { ScrollView, View, Text, StyleSheet } from 'react-native';<br /><br />const CollapsibleHeader = () => {<br /> const [scrollY, setScrollY] = useState(0);<br /> const [isCollapsed, setIsCollapsed] = useState(false);<br /><br /> const handleScroll = (event) => {<br /> const offsetY = event.nativeEvent.contentOffset.y;<br /> setScrollY(offsetY);<br /> setIsCollapsed(offsetY > 100);<br /> };<br /><br /> return (<br /> <View style={styles.container}><br /> <ScrollView onScroll={handleScroll} scrollEventThrottle={16}><br /> <View style={[styles.header, isCollapsed ? styles.collapsed : styles.expanded]}><br /> <Text style={styles.headerText}>Collapsible Header</Text><br /> </View><br /> <View style={styles.content}><br /> <Text>Scroll to collapse header</Text><br /> </View><br /> </ScrollView><br /> </View>,<br /> );<br />};<br /><br />const styles = StyleSheet.create({<br /> container: { flex: 1 },<br /> header: { backgroundColor: '#3b82f6', justifyContent: 'center', alignItems: 'center' },<br /> collapsed: { height: 50 },<br /> expanded: { height: 100 },<br /> headerText: { color: 'white', fontSize: 20 },<br /> content: { padding: 20, backgroundColor: '#f3f4f6' },<br />});<br /><br />export default CollapsibleHeader;
Note: The
scrollEventThrottle property should be set to a value like 16ms to ensure smooth scrolling performance.
9. Creating Tab Views
Example: Basic Tab View with React Navigation
import 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
| Property | Description | Default |
|---|---|---|
| screenOptions | Object to customize tab bar appearance and behavior | {} |
| initialRouteName | Name of the route to start at | First screen in list |
| backBehavior | Behavior when pressing back button | "initialRoute" |
Note: Tab views in React Native are typically implemented using
@react-navigation for native-like behavior.Example: Custom Tab Bar Icons
import { Ionicons } from '@expo/vector-icons';
function CustomTabBarIcon({ name, focused }) {
return (
<Ionicons
name={name}
size={24}
color={focused ? '#007AFF' : '#8E8E93'}
/>
);
}
const screenOptions = {
tabBarIcon: ({ focused, route }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused ? 'home' : 'home-outline';
} else if (route.name === 'Profile') {
iconName = focused ? 'person' : 'person-outline';
}
return <CustomTabBarIcon name={iconName} focused={focused} />;
},
};
10. Implementing Parallax Effects
| Property | Description | Values |
|---|---|---|
| parallaxFactor | Controls the intensity of the parallax effect | 0.0 - 1.0 |
| speed | Adjusts the scroll speed of the parallax layer | number |
| scrollDirection | Defines the direction of scroll that triggers the effect | 'vertical' | 'horizontal' |
Example: Basic Parallax Component
import React from 'react';
import { Animated, ScrollView } from 'react-native';
const ParallaxEffect = () => {
const scrollY = new Animated.Value(0);
return (
<ScrollView
onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], { useNativeDriver: true })}
scrollEventThrottle={16}
>
<Animated.View
style={{
height: 300,
backgroundColor: '#ff6b6b',
transform: [
{
translateY: scrollY.interpolate({
inputRange: [0, 500],
outputRange: [0, -100],
}),
},
],
}}
>
<Text style={{ fontSize: 24, color: 'white', padding: 20 }}>Parallax Header</Text>
</Animated.View>
</ScrollView>
);
};
export default ParallaxEffect;
Note: Use
useNativeDriver: true for better performance in scroll animations.
Warning: Avoid heavy content in parallax layers as it can cause jank.