Skip to main content

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

<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 Modal component for custom modal UIs in React Native
  • Set animationType to slide, fade, or none
  • Control visibility with the visible prop
  • Use transparent for 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 &#x27;react&#x27;;
import { createBottomTabNavigator } from &#x27;@react-navigation/bottom-tabs&#x27;;
import { NavigationContainer } from &#x27;@react-navigation/native&#x27;;

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 &#x27;@expo/vector-icons&#x27;;

function CustomTabBarIcon({ name, focused }) {
  return (
    <Ionicons
      name={name}
      size={24}
      color={focused ? &#x27;#007AFF&#x27; : &#x27;#8E8E93&#x27;}
    />
  );
}

const screenOptions = {
  tabBarIcon: ({ focused, route }) => {
    let iconName;
    if (route.name === &#x27;Home&#x27;) {
      iconName = focused ? &#x27;home&#x27; : &#x27;home-outline&#x27;;
    } else if (route.name === &#x27;Profile&#x27;) {
      iconName = focused ? &#x27;person&#x27; : &#x27;person-outline&#x27;;
    }
    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.

Was this article helpful?