reactnative
/

React Native Layout – Flexbox, Positioning & Responsive Design

Last Sync: Today

On this page

7
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

reactnative

React Native Layout – Flexbox, Positioning & Responsive Design

React Native Layout – Building Responsive Mobile UIs

React Native uses a flexbox-based layout system that's similar to CSS Flexbox but with mobile-specific considerations. Unlike web CSS, the default flexDirection is column (not row), and all dimensions are unitless (representing logical pixels). In 2026, mastering layout is essential for creating apps that work seamlessly across iPhones, iPads, Android devices, and foldables. This guide covers everything from basic flexbox to advanced responsive patterns.

  1. Flexbox Fundamentals

Flexbox is the primary layout system in React Native. Understanding these properties is critical for any layout task.

React JSXRead-only
1
import React from 'react';
import { View, Text, StyleSheet, ScrollView } from 'react-native';

const FlexboxFundamentals = () => {
  return (
    <ScrollView style={styles.container}>
      <Text style={styles.title}>Flexbox Fundamentals</Text>

      {/* 1. Flex Direction */}
      <Text style={styles.sectionTitle}>1. flexDirection: 'row' vs 'column'</Text>
      <View style={styles.rowContainer}>
        <View style={[styles.box, { backgroundColor: '#FF3B30' }]}><Text>1</Text></View>
        <View style={[styles.box, { backgroundColor: '#FF9500' }]}><Text>2</Text></View>
        <View style={[styles.box, { backgroundColor: '#FFCC00' }]}><Text>3</Text></View>
      </View>
      
      <View style={styles.columnContainer}>
        <View style={[styles.box, { backgroundColor: '#4CD964' }]}><Text>1</Text></View>
        <View style={[styles.box, { backgroundColor: '#007AFF' }]}><Text>2</Text></View>
        <View style={[styles.box, { backgroundColor: '#5856D6' }]}><Text>3</Text></View>
      </View>

      {/* 2. Justify Content */}
      <Text style={styles.sectionTitle}>2. justifyContent Options</Text>
      
      <Text style={styles.subsection}>flex-start (default)</Text>
      <View style={[styles.justifyRow, { justifyContent: 'flex-start' }]}>
        <View style={styles.smallBox} /><View style={styles.smallBox} /><View style={styles.smallBox} />
      </View>

      <Text style={styles.subsection}>center</Text>
      <View style={[styles.justifyRow, { justifyContent: 'center' }]}>
        <View style={styles.smallBox} /><View style={styles.smallBox} /><View style={styles.smallBox} />
      </View>

      <Text style={styles.subsection}>space-between</Text>
      <View style={[styles.justifyRow, { justifyContent: 'space-between' }]}>
        <View style={styles.smallBox} /><View style={styles.smallBox} /><View style={styles.smallBox} />
      </View>

      <Text style={styles.subsection}>space-around</Text>
      <View style={[styles.justifyRow, { justifyContent: 'space-around' }]}>
        <View style={styles.smallBox} /><View style={styles.smallBox} /><View style={styles.smallBox} />
      </View>

      <Text style={styles.subsection}>space-evenly</Text>
      <View style={[styles.justifyRow, { justifyContent: 'space-evenly' }]}>
        <View style={styles.smallBox} /><View style={styles.smallBox} /><View style={styles.smallBox} />
      </View>

      {/* 3. Align Items */}
      <Text style={styles.sectionTitle}>3. alignItems Options</Text>
      
      <Text style={styles.subsection}>flex-start</Text>
      <View style={[styles.alignRow, { alignItems: 'flex-start' }]}>
        <View style={[styles.variableBox, { height: 40 }]} />
        <View style={[styles.variableBox, { height: 60 }]} />
        <View style={[styles.variableBox, { height: 80 }]} />
      </View>

      <Text style={styles.subsection}>center</Text>
      <View style={[styles.alignRow, { alignItems: 'center' }]}>
        <View style={[styles.variableBox, { height: 40 }]} />
        <View style={[styles.variableBox, { height: 60 }]} />
        <View style={[styles.variableBox, { height: 80 }]} />
      </View>

      <Text style={styles.subsection}>flex-end</Text>
      <View style={[styles.alignRow, { alignItems: 'flex-end' }]}>
        <View style={[styles.variableBox, { height: 40 }]} />
        <View style={[styles.variableBox, { height: 60 }]} />
        <View style={[styles.variableBox, { height: 80 }]} />
      </View>

      <Text style={styles.subsection}>stretch</Text>
      <View style={[styles.alignRow, { alignItems: 'stretch' }]}>
        <View style={[styles.variableBox, { width: 'auto' }]} />
        <View style={[styles.variableBox, { width: 'auto' }]} />
        <View style={[styles.variableBox, { width: 'auto' }]} />
      </View>

      {/* 4. Flex Wrap */}
      <Text style={styles.sectionTitle}>4. flexWrap: 'wrap'</Text>
      <View style={styles.wrapContainer}>
        {[...Array(10)].map((_, i) => (
          <View key={i} style={[styles.wrapBox, { backgroundColor: '#34C759' }]}>
            <Text style={styles.wrapText}>{i + 1}</Text>
          </View>
        ))}
      </View>

      {/* 5. Flex Grow & Shrink */}
      <Text style={styles.sectionTitle}>5. flex: 1 (Grow to fill space)</Text>
      <View style={styles.flexContainer}>
        <View style={[styles.fixedBox, { backgroundColor: '#FF3B30', width: 80 }]}>
          <Text>Fixed</Text>
        </View>
        <View style={[styles.growBox, { backgroundColor: '#007AFF', flex: 1 }]}>
          <Text>Grows (flex:1)</Text>
        </View>
        <View style={[styles.growBox, { backgroundColor: '#34C759', flex: 2 }]}>
          <Text>Grows More (flex:2)</Text>
        </View>
      </View>

      {/* 6. Align Self */}
      <Text style={styles.sectionTitle}>6. alignSelf (override parent)</Text>
      <View style={styles.alignSelfContainer}>
        <View style={[styles.alignSelfBox, { alignSelf: 'flex-start', backgroundColor: '#FF3B30' }]}>
          <Text>flex-start</Text>
        </View>
        <View style={[styles.alignSelfBox, { alignSelf: 'center', backgroundColor: '#007AFF' }]}>
          <Text>center</Text>
        </View>
        <View style={[styles.alignSelfBox, { alignSelf: 'flex-end', backgroundColor: '#34C759' }]}>
          <Text>flex-end</Text>
        </View>
      </View>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: '#fff'
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginTop: 20,
    marginBottom: 12
  },
  subsection: {
    fontSize: 14,
    fontWeight: '500',
    marginTop: 8,
    marginBottom: 4,
    color: '#666'
  },
  rowContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#f0f0f0',
    padding: 10,
    borderRadius: 8
  },
  columnContainer: {
    flexDirection: 'column',
    alignItems: 'center',
    backgroundColor: '#f0f0f0',
    padding: 10,
    borderRadius: 8,
    gap: 10
  },
  box: {
    width: 60,
    height: 60,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8
  },
  smallBox: {
    width: 50,
    height: 50,
    backgroundColor: '#007AFF',
    borderRadius: 8
  },
  justifyRow: {
    flexDirection: 'row',
    backgroundColor: '#f0f0f0',
    padding: 10,
    borderRadius: 8,
    marginBottom: 8
  },
  alignRow: {
    flexDirection: 'row',
    backgroundColor: '#f0f0f0',
    padding: 10,
    borderRadius: 8,
    height: 120,
    marginBottom: 8,
    gap: 8
  },
  variableBox: {
    width: 60,
    backgroundColor: '#007AFF',
    borderRadius: 8
  },
  wrapContainer: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    gap: 8,
    backgroundColor: '#f0f0f0',
    padding: 10,
    borderRadius: 8
  },
  wrapBox: {
    width: 60,
    height: 60,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8
  },
  wrapText: {
    color: '#fff',
    fontWeight: 'bold'
  },
  flexContainer: {
    flexDirection: 'row',
    backgroundColor: '#f0f0f0',
    padding: 10,
    borderRadius: 8,
    height: 80,
    gap: 8
  },
  fixedBox: {
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8
  },
  growBox: {
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8
  },
  alignSelfContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#f0f0f0',
    padding: 20,
    borderRadius: 8,
    height: 150
  },
  alignSelfBox: {
    width: 70,
    height: 50,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8
  }
});

export default FlexboxFundamentals;

// Flexbox Property Reference:
// 
// Container Properties:
// - flexDirection: 'row' | 'column' | 'row-reverse' | 'column-reverse' (default: 'column')
// - justifyContent: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly'
// - alignItems: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline'
// - flexWrap: 'wrap' | 'nowrap' | 'wrap-reverse'
// - alignContent: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'space-between' | 'space-around'
// - gap: number (spacing between children)
// - rowGap: number
// - columnGap: number
//
// Item Properties:
// - flex: number (0 = no grow, positive = grow proportionally)
// - flexGrow: number
// - flexShrink: number
// - flexBasis: number | 'auto'
// - alignSelf: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline'
// - aspectRatio: number

  1. Positioning (Relative vs Absolute)

React Native supports relative (default) and absolute positioning. Absolute positioning is useful for overlays, badges, headers, and custom layouts.

React JSXRead-only
1
import React, { useState } from 'react';
import {
  View,
  Text,
  StyleSheet,
  TouchableOpacity,
  ScrollView,
  Image
} from 'react-native';

const PositioningExamples = () => {
  const [showOverlay, setShowOverlay] = useState(false);

  return (
    <ScrollView style={styles.container}>
      <Text style={styles.title}>Positioning: Relative vs Absolute</Text>

      {/* 1. Relative Positioning (default) */}
      <Text style={styles.sectionTitle}>1. Relative Positioning (Default)</Text>
      <View style={styles.relativeContainer}>
        <View style={[styles.item, { backgroundColor: '#FF3B30' }]}>
          <Text>Item 1</Text>
        </View>
        <View style={[styles.item, { backgroundColor: '#007AFF' }]}>
          <Text>Item 2</Text>
        </View>
        <View style={[styles.item, { backgroundColor: '#34C759' }]}>
          <Text>Item 3</Text>
        </View>
      </View>

      {/* 2. Relative with offset */}
      <Text style={styles.sectionTitle}>2. Relative with top/left offset</Text>
      <View style={styles.offsetContainer}>
        <View style={[styles.offsetItem, { backgroundColor: '#FF3B30' }]}>
          <Text>Normal</Text>
        </View>
        <View style={[styles.offsetItem, { 
          backgroundColor: '#007AFF',
          position: 'relative',
          top: 20,
          left: 20
        }]}>
          <Text>Offset 20,20</Text>
        </View>
        <View style={[styles.offsetItem, { backgroundColor: '#34C759' }]}>
          <Text>Normal</Text>
        </View>
      </View>

      {/* 3. Absolute Positioning - Badge Example */}
      <Text style={styles.sectionTitle}>3. Absolute Positioning - Badge</Text>
      <View style={styles.badgeContainer}>
        <View style={styles.iconContainer}>
          <Text style={styles.iconText}>📧</Text>
          <View style={styles.badge}>
            <Text style={styles.badgeText}>3</Text>
          </View>
        </View>
        <Text>Notifications Icon with Badge</Text>
      </View>

      {/* 4. Absolute Positioning - Overlay */}
      <Text style={styles.sectionTitle}>4. Absolute Positioning - Image Overlay</Text>
      <TouchableOpacity 
        style={styles.imageContainer}
        onPress={() => setShowOverlay(!showOverlay)}
      >
        <Image
          source={{ uri: 'https://picsum.photos/300/200' }}
          style={styles.image}
        />
        {showOverlay && (
          <View style={styles.imageOverlay}>
            <Text style={styles.overlayText}>Tap to close</Text>
          </View>
        )}
        <View style={styles.imageLabel}>
          <Text style={styles.labelText}>Tap for overlay</Text>
        </View>
      </TouchableOpacity>

      {/* 5. Absolute Positioning - Centered Modal */}
      <Text style={styles.sectionTitle}>5. Absolute Centered Modal</Text>
      <View style={styles.modalTriggerContainer}>
        <TouchableOpacity 
          style={styles.modalButton}
          onPress={() => setShowOverlay(true)}
        >
          <Text style={styles.buttonText}>Show Modal</Text>
        </TouchableOpacity>
      </View>

      {showOverlay && (
        <TouchableOpacity 
          style={styles.modalOverlay}
          activeOpacity={1}
          onPress={() => setShowOverlay(false)}
        >
          <View style={styles.modalContent}>
            <Text style={styles.modalTitle}>Absolute Modal</Text>
            <Text style={styles.modalText}>This modal is positioned absolutely with centered content.</Text>
            <TouchableOpacity 
              style={styles.closeButton}
              onPress={() => setShowOverlay(false)}
            >
              <Text style={styles.closeButtonText}>Close</Text>
            </TouchableOpacity>
          </View>
        </TouchableOpacity>
      )}

      {/* 6. Z-Index Layering */}
      <Text style={styles.sectionTitle}>6. Z-Index Layering</Text>
      <View style={styles.zIndexContainer}>
        <View style={[styles.zIndexBox, { 
          backgroundColor: '#FF3B30', 
          zIndex: 3,
          top: 0,
          left: 0
        }]}>
          <Text>z-index:3</Text>
        </View>
        <View style={[styles.zIndexBox, { 
          backgroundColor: '#007AFF', 
          zIndex: 2,
          top: -30,
          left: 30
        }]}>
          <Text>z-index:2</Text>
        </View>
        <View style={[styles.zIndexBox, { 
          backgroundColor: '#34C759', 
          zIndex: 1,
          top: -60,
          left: 60
        }]}>
          <Text>z-index:1</Text>
        </View>
      </View>

      {/* 7. Sticky Header Pattern */}
      <Text style={styles.sectionTitle}>7. Sticky Header (using position: 'sticky')</Text>
      <View style={styles.stickyContainer}>
        <View style={styles.stickyHeader}>
          <Text style={styles.stickyHeaderText}>This header sticks on scroll</Text>
        </View>
        {[...Array(10)].map((_, i) => (
          <View key={i} style={styles.stickyItem}>
            <Text>Scrollable content {i + 1}</Text>
          </View>
        ))}
      </View>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: '#fff'
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginTop: 20,
    marginBottom: 12
  },
  // Relative positioning
  relativeContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#f0f0f0',
    padding: 10,
    borderRadius: 8
  },
  item: {
    width: 60,
    height: 60,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8
  },
  // Offset positioning
  offsetContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#f0f0f0',
    padding: 20,
    borderRadius: 8,
    minHeight: 120
  },
  offsetItem: {
    width: 60,
    height: 60,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8
  },
  // Badge example
  badgeContainer: {
    alignItems: 'center',
    padding: 20,
    backgroundColor: '#f0f0f0',
    borderRadius: 8
  },
  iconContainer: {
    position: 'relative',
    width: 50,
    height: 50,
    justifyContent: 'center',
    alignItems: 'center'
  },
  iconText: {
    fontSize: 40
  },
  badge: {
    position: 'absolute',
    top: -5,
    right: -10,
    backgroundColor: '#FF3B30',
    borderRadius: 10,
    minWidth: 20,
    height: 20,
    justifyContent: 'center',
    alignItems: 'center',
    paddingHorizontal: 4
  },
  badgeText: {
    color: '#fff',
    fontSize: 12,
    fontWeight: 'bold'
  },
  // Image overlay
  imageContainer: {
    position: 'relative',
    borderRadius: 12,
    overflow: 'hidden'
  },
  image: {
    width: '100%',
    height: 200,
    borderRadius: 12
  },
  imageOverlay: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: 'rgba(0,0,0,0.7)',
    justifyContent: 'center',
    alignItems: 'center'
  },
  imageLabel: {
    position: 'absolute',
    bottom: 10,
    left: 10,
    backgroundColor: 'rgba(0,0,0,0.6)',
    paddingHorizontal: 12,
    paddingVertical: 4,
    borderRadius: 20
  },
  labelText: {
    color: '#fff',
    fontSize: 12
  },
  overlayText: {
    color: '#fff',
    fontSize: 18,
    fontWeight: 'bold'
  },
  // Modal
  modalTriggerContainer: {
    alignItems: 'center',
    padding: 10
  },
  modalButton: {
    backgroundColor: '#007AFF',
    paddingHorizontal: 20,
    paddingVertical: 12,
    borderRadius: 8
  },
  buttonText: {
    color: '#fff',
    fontWeight: '600'
  },
  modalOverlay: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: 'rgba(0,0,0,0.5)',
    justifyContent: 'center',
    alignItems: 'center'
  },
  modalContent: {
    backgroundColor: '#fff',
    borderRadius: 12,
    padding: 20,
    width: '80%',
    alignItems: 'center'
  },
  modalTitle: {
    fontSize: 20,
    fontWeight: 'bold',
    marginBottom: 12
  },
  modalText: {
    textAlign: 'center',
    marginBottom: 20
  },
  closeButton: {
    backgroundColor: '#007AFF',
    paddingHorizontal: 20,
    paddingVertical: 10,
    borderRadius: 8
  },
  closeButtonText: {
    color: '#fff',
    fontWeight: '600'
  },
  // Z-index
  zIndexContainer: {
    height: 100,
    position: 'relative',
    marginBottom: 20
  },
  zIndexBox: {
    position: 'absolute',
    width: 80,
    height: 80,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8
  },
  // Sticky header
  stickyContainer: {
    maxHeight: 300,
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
    overflow: 'hidden'
  },
  stickyHeader: {
    position: 'sticky',
    top: 0,
    backgroundColor: '#007AFF',
    padding: 12,
    zIndex: 1
  },
  stickyHeaderText: {
    color: '#fff',
    fontWeight: 'bold',
    textAlign: 'center'
  },
  stickyItem: {
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#e0e0e0',
    backgroundColor: '#fff'
  }
});

export default PositioningExamples;

// Positioning Reference:
// 
// position: 'relative' (default)
// - Element positioned relative to its normal flow position
// - top, bottom, left, right offset from normal position
//
// position: 'absolute'
// - Element positioned relative to its nearest positioned ancestor
// - Removed from normal document flow
// - Other elements ignore absolute positioned elements
// - Use zIndex to control stacking order
//
// position: 'sticky' (iOS only, limited support)
// - Behaves as relative until scroll threshold, then fixed
//
// zIndex: number
// - Controls stacking order (higher number = on top)
// - Only works on positioned elements (relative/absolute)

  1. Responsive Layout Patterns

Create layouts that adapt to different screen sizes, orientations, and devices using responsive techniques.

React JSXRead-only
1
import React from 'react';
import {
  View,
  Text,
  StyleSheet,
  ScrollView,
  useWindowDimensions,
  Platform
} from 'react-native';

const ResponsiveLayouts = () => {
  const { width, height } = useWindowDimensions();
  const isLandscape = width > height;
  const isTablet = width >= 768;
  const isSmallDevice = width <= 375;

  // Responsive grid columns
  const getGridColumns = () => {
    if (isTablet) return 4;
    if (isLandscape) return 3;
    return 2;
  };

  const numColumns = getGridColumns();
  const gap = 12;
  const itemWidth = (width - (gap * (numColumns + 1))) / numColumns;

  // Responsive font sizes
  const getFontSize = () => {
    if (isTablet) return 18;
    if (isSmallDevice) return 12;
    return 14;
  };

  return (
    <ScrollView style={styles.container}>
      <Text style={styles.title}>Responsive Layout Patterns</Text>

      {/* Device Info Card */}
      <View style={styles.infoCard}>
        <Text style={styles.infoText}>Width: {Math.round(width)}px</Text>
        <Text style={styles.infoText}>Height: {Math.round(height)}px</Text>
        <Text style={styles.infoText}>Orientation: {isLandscape ? 'Landscape' : 'Portrait'}</Text>
        <Text style={styles.infoText}>Device: {isTablet ? 'Tablet' : 'Phone'}</Text>
        <Text style={styles.infoText}>Platform: {Platform.OS}</Text>
      </View>

      {/* Responsive Grid */}
      <Text style={styles.sectionTitle}>Responsive Grid ({numColumns} columns)</Text>
      <View style={styles.gridContainer}>
        {[...Array(8)].map((_, i) => (
          <View
            key={i}
            style={[
              styles.gridItem,
              {
                width: itemWidth,
                height: itemWidth,
                backgroundColor: `hsl(${i * 45}, 70%, 50%)`
              }
            ]}
          >
            <Text style={styles.gridText}>{i + 1}</Text>
          </View>
        ))}
      </View>

      {/* Responsive Layout: Column vs Row */}
      <Text style={styles.sectionTitle}>Responsive Layout (Column/Row)</Text>
      {isTablet ? (
        <View style={styles.twoColumnLayout}>
          <View style={styles.column}>
            <Text style={styles.columnTitle}>Column 1</Text>
            <Text>Sidebar content for tablets</Text>
          </View>
          <View style={styles.column}>
            <Text style={styles.columnTitle}>Column 2</Text>
            <Text>Main content area</Text>
          </View>
        </View>
      ) : (
        <View style={styles.singleColumnLayout}>
          <Text style={styles.columnTitle}>Single Column (Phone)</Text>
          <Text>Stacked vertically on phones</Text>
        </View>
      )}

      {/* Responsive Cards */}
      <Text style={styles.sectionTitle}>Responsive Cards</Text>
      <View style={styles.cardsContainer}>
        {[1, 2, 3].map((i) => (
          <View
            key={i}
            style={[
              styles.card,
              isTablet && styles.cardTablet,
              isSmallDevice && styles.cardSmall
            ]}
          >
            <Text style={[styles.cardTitle, { fontSize: getFontSize() + 2 }]}>
              Card {i}
            </Text>
            <Text style={[styles.cardText, { fontSize: getFontSize() }]}>
              Responsive card that adapts to screen size.
            </Text>
          </View>
        ))}
      </View>

      {/* Percentage-based widths */}
      <Text style={styles.sectionTitle}>Percentage Widths</Text>
      <View style={styles.percentageContainer}>
        <View style={[styles.percentageBox, { width: '25%', backgroundColor: '#FF3B30' }]}>
          <Text style={styles.percentageText}>25%</Text>
        </View>
        <View style={[styles.percentageBox, { width: '50%', backgroundColor: '#007AFF' }]}>
          <Text style={styles.percentageText}>50%</Text>
        </View>
        <View style={[styles.percentageBox, { width: '25%', backgroundColor: '#34C759' }]}>
          <Text style={styles.percentageText}>25%</Text>
        </View>
      </View>

      {/* Dynamic spacing */}
      <Text style={styles.sectionTitle}>Dynamic Spacing</Text>
      <View style={[styles.dynamicSpacing, { padding: isTablet ? 24 : 16 }]}>
        <Text>Spacing adapts to screen size</Text>
        <View style={[styles.spacingBox, { marginTop: isTablet ? 20 : 12 }]} />
        <Text>Tablets get more breathing room</Text>
      </View>

      {/* Orientation-specific layout */}
      <Text style={styles.sectionTitle}>Orientation-Specific</Text>
      {isLandscape ? (
        <View style={styles.landscapeLayout}>
          <View style={styles.landscapeSidebar}>
            <Text>Sidebar</Text>
          </View>
          <View style={styles.landscapeContent}>
            <Text>Main Content (Landscape Optimized)</Text>
          </View>
        </View>
      ) : (
        <View style={styles.portraitLayout}>
          <View style={styles.portraitHeader}>
            <Text>Header (Portrait)</Text>
          </View>
          <View style={styles.portraitContent}>
            <Text>Scrollable Content</Text>
          </View>
        </View>
      )}
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: '#fff'
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginTop: 20,
    marginBottom: 12
  },
  infoCard: {
    backgroundColor: '#f0f0f0',
    padding: 16,
    borderRadius: 12,
    gap: 4
  },
  infoText: {
    fontSize: 14,
    color: '#333'
  },
  gridContainer: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    gap: 12
  },
  gridItem: {
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center'
  },
  gridText: {
    color: '#fff',
    fontWeight: 'bold',
    fontSize: 18
  },
  twoColumnLayout: {
    flexDirection: 'row',
    gap: 16
  },
  column: {
    flex: 1,
    backgroundColor: '#f0f0f0',
    padding: 16,
    borderRadius: 8
  },
  columnTitle: {
    fontWeight: 'bold',
    marginBottom: 8
  },
  singleColumnLayout: {
    backgroundColor: '#f0f0f0',
    padding: 16,
    borderRadius: 8
  },
  cardsContainer: {
    gap: 12
  },
  card: {
    backgroundColor: '#f9f9f9',
    padding: 16,
    borderRadius: 12,
    borderWidth: 1,
    borderColor: '#e0e0e0'
  },
  cardTablet: {
    padding: 20
  },
  cardSmall: {
    padding: 12
  },
  cardTitle: {
    fontWeight: 'bold',
    marginBottom: 8
  },
  cardText: {
    color: '#666'
  },
  percentageContainer: {
    flexDirection: 'row',
    height: 60,
    borderRadius: 8,
    overflow: 'hidden'
  },
  percentageBox: {
    justifyContent: 'center',
    alignItems: 'center'
  },
  percentageText: {
    color: '#fff',
    fontWeight: 'bold'
  },
  dynamicSpacing: {
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
    alignItems: 'center'
  },
  spacingBox: {
    width: 50,
    height: 50,
    backgroundColor: '#007AFF',
    borderRadius: 8
  },
  landscapeLayout: {
    flexDirection: 'row',
    height: 150,
    gap: 12
  },
  landscapeSidebar: {
    width: '30%',
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center'
  },
  landscapeContent: {
    flex: 1,
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center'
  },
  portraitLayout: {
    height: 150,
    gap: 8
  },
  portraitHeader: {
    height: '30%',
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center'
  },
  portraitContent: {
    flex: 1,
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center'
  }
});

export default ResponsiveLayouts;

  1. Safe Area & Edge Handling

Handle notches, dynamic islands, and home indicators using SafeAreaView and SafeAreaProvider. This is critical for modern iPhones and Android devices with cutouts.

React JSXRead-only
1
import React from 'react';
import {
  View,
  Text,
  StyleSheet,
  ScrollView,
  Platform,
  StatusBar
} from 'react-native';
import { SafeAreaView, SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';

// Method 1: Using SafeAreaView (wraps content automatically)
const BasicSafeAreaExample = () => {
  return (
    <SafeAreaView style={styles.safeArea}>
      <View style={styles.content}>
        <Text style={styles.title}>SafeAreaView Example</Text>
        <Text>This content automatically avoids notches and home indicators</Text>
      </View>
    </SafeAreaView>
  );
};

// Method 2: Using useSafeAreaInsets hook for custom control
const CustomInsetsExample = () => {
  const insets = useSafeAreaInsets();

  return (
    <View style={[
      styles.container,
      {
        paddingTop: insets.top,
        paddingBottom: insets.bottom,
        paddingLeft: insets.left,
        paddingRight: insets.right
      }
    ]}>
      <View style={styles.header}>
        <Text>Custom Header (respects safe area)</Text>
      </View>
      <ScrollView style={styles.scrollContent}>
        <Text>Safe area insets:</Text>
        <Text>Top: {insets.top}</Text>
        <Text>Bottom: {insets.bottom}</Text>
        <Text>Left: {insets.left}</Text>
        <Text>Right: {insets.right}</Text>
      </ScrollView>
      <View style={[styles.footer, { paddingBottom: insets.bottom }]}>
        <Text>Footer respects bottom safe area</Text>
      </View>
    </View>
  );
};

// Method 3: Platform-specific status bar handling
const StatusBarExample = () => {
  const insets = useSafeAreaInsets();

  return (
    <View style={styles.container}>
      {/* Status bar spacing */}
      <View style={{ height: Platform.OS === 'ios' ? insets.top : StatusBar.currentHeight }} />
      
      <View style={styles.header}>
        <Text>Status Bar Spacing Applied</Text>
      </View>
      
      <ScrollView style={styles.content}>
        <Text>Content that scrolls below the header</Text>
      </ScrollView>
    </View>
  );
};

// Complete app with SafeAreaProvider
const AppWithSafeArea = () => {
  return (
    <SafeAreaProvider>
      <SafeAreaView style={styles.fullScreen}>
        <TabNavigator />
      </SafeAreaView>
    </SafeAreaProvider>
  );
};

// Tab bar with safe area
const TabNavigator = () => {
  const insets = useSafeAreaInsets();

  return (
    <View style={styles.tabContainer}>
      <View style={styles.tabContent}>
        <Text>Main Content</Text>
      </View>
      <View style={[styles.tabBar, { paddingBottom: insets.bottom || 10 }]}>
        <Text>Tab 1</Text>
        <Text>Tab 2</Text>
        <Text>Tab 3</Text>
      </View>
    </View>
  );
};

// Handling different device types
const DeviceAwareLayout = () => {
  const insets = useSafeAreaInsets();
  const hasNotch = insets.top > 20;
  const hasDynamicIsland = insets.top > 50; // Approximate

  return (
    <SafeAreaView style={styles.safeArea}>
      <View style={[
        styles.header,
        hasNotch && styles.headerWithNotch,
        hasDynamicIsland && styles.headerWithDynamicIsland
      ]}>
        <Text style={styles.headerText}>
          {hasDynamicIsland ? 'Dynamic Island Device' : hasNotch ? 'Notch Device' : 'Standard Device'}
        </Text>
      </View>
      
      <ScrollView contentContainerStyle={styles.scrollContent}>
        <Text>Content adjusts based on device type</Text>
        <View style={styles.infoCard}>
          <Text>Safe Area Top: {insets.top}</Text>
          <Text>Safe Area Bottom: {insets.bottom}</Text>
          <Text>Has Notch: {hasNotch ? 'Yes' : 'No'}</Text>
          <Text>Has Dynamic Island: {hasDynamicIsland ? 'Yes' : 'No'}</Text>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  fullScreen: {
    flex: 1
  },
  safeArea: {
    flex: 1,
    backgroundColor: '#fff'
  },
  container: {
    flex: 1,
    backgroundColor: '#fff'
  },
  content: {
    flex: 1,
    padding: 16
  },
  title: {
    fontSize: 20,
    fontWeight: 'bold',
    marginBottom: 12
  },
  header: {
    backgroundColor: '#007AFF',
    padding: 16,
    alignItems: 'center'
  },
  headerWithNotch: {
    paddingTop: 32
  },
  headerWithDynamicIsland: {
    paddingTop: 54
  },
  headerText: {
    color: '#fff',
    fontWeight: 'bold'
  },
  footer: {
    backgroundColor: '#f0f0f0',
    padding: 16,
    alignItems: 'center'
  },
  scrollContent: {
    padding: 16
  },
  infoCard: {
    backgroundColor: '#f0f0f0',
    padding: 16,
    borderRadius: 8,
    marginTop: 16,
    gap: 8
  },
  tabContainer: {
    flex: 1
  },
  tabContent: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  tabBar: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#f0f0f0',
    paddingTop: 10,
    paddingHorizontal: 16
  }
});

export { 
  BasicSafeAreaExample, 
  CustomInsetsExample, 
  DeviceAwareLayout,
  AppWithSafeArea
};

// Installation for react-native-safe-area-context:
// npm install react-native-safe-area-context
// cd ios && pod install

// Usage: Wrap your root component with SafeAreaProvider

  1. Scroll View Layout Patterns

Master ScrollView layout patterns including nested scrolling, keyboard avoidance, and pull-to-refresh.

React JSXRead-only
1
import React, { useRef } from 'react';
import {
  View,
  Text,
  StyleSheet,
  ScrollView,
  TextInput,
  TouchableOpacity,
  RefreshControl,
  KeyboardAvoidingView,
  Platform,
  Dimensions
} from 'react-native';

const ScrollViewPatterns = () => {
  const [refreshing, setRefreshing] = React.useState(false);
  const scrollViewRef = useRef(null);

  // Pull to refresh
  const onRefresh = React.useCallback(() => {
    setRefreshing(true);
    setTimeout(() => {
      setRefreshing(false);
    }, 2000);
  }, []);

  // Scroll to top
  const scrollToTop = () => {
    scrollViewRef.current?.scrollTo({ y: 0, animated: true });
  };

  // Scroll to specific position
  const scrollToPosition = (y: number) => {
    scrollViewRef.current?.scrollTo({ y, animated: true });
  };

  return (
    <KeyboardAvoidingView
      style={styles.container}
      behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
      keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 20}
    >
      {/* Basic ScrollView with refresh control */}
      <ScrollView
        ref={scrollViewRef}
        showsVerticalScrollIndicator={true}
        showsHorizontalScrollIndicator={false}
        refreshControl={
          <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
        }
        contentContainerStyle={styles.scrollContent}
        // Keyboard behavior
        keyboardDismissMode="interactive"
        keyboardShouldPersistTaps="handled"
      >
        <Text style={styles.title}>ScrollView Patterns</Text>

        {/* Horizontal ScrollView */}
        <Text style={styles.sectionTitle}>Horizontal Scrolling</Text>
        <ScrollView
          horizontal={true}
          showsHorizontalScrollIndicator={false}
          style={styles.horizontalScroll}
          contentContainerStyle={styles.horizontalContent}
        >
          {[...Array(10)].map((_, i) => (
            <View key={i} style={[styles.horizontalItem, { backgroundColor: `hsl(${i * 36}, 70%, 50%)` }]}>
              <Text style={styles.horizontalText}>{i + 1}</Text>
            </View>
          ))}
        </ScrollView>

        {/* Nested ScrollViews (requires nestedScrollEnabled on Android) */}
        <Text style={styles.sectionTitle}>Nested Scrolling</Text>
        <View style={styles.nestedContainer}>
          <ScrollView
            nestedScrollEnabled={Platform.OS === 'android'}
            style={styles.nestedScroll}
            showsVerticalScrollIndicator={false}
          >
            {[...Array(5)].map((_, i) => (
              <View key={i} style={styles.nestedItem}>
                <Text>Nested Content {i + 1}</Text>
              </View>
            ))}
          </ScrollView>
        </View>

        {/* Form with keyboard avoidance */}
        <Text style={styles.sectionTitle}>Form with Keyboard Avoidance</Text>
        <View style={styles.form}>
          <TextInput style={styles.input} placeholder="Name" />
          <TextInput style={styles.input} placeholder="Email" keyboardType="email-address" />
          <TextInput
            style={[styles.input, styles.textArea]}
            placeholder="Message"
            multiline
            numberOfLines={4}
          />
          <TouchableOpacity style={styles.submitButton}>
            <Text style={styles.submitText}>Submit</Text>
          </TouchableOpacity>
        </View>

        {/* Sticky headers in ScrollView */}
        <Text style={styles.sectionTitle}>Sticky Elements</Text>
        <View style={styles.stickyContainer}>
          <View style={styles.stickyHeader}>
            <Text style={styles.stickyText}>This header sticks while scrolling</Text>
          </View>
          {[...Array(15)].map((_, i) => (
            <View key={i} style={styles.stickyItem}>
              <Text>Scrollable content item {i + 1}</Text>
            </View>
          ))}
        </View>

        {/* Scroll to top button */}
        <TouchableOpacity style={styles.scrollTopButton} onPress={scrollToTop}>
          <Text style={styles.scrollTopText}>↑ Scroll to Top</Text>
        </TouchableOpacity>

        {/* Content footer */}
        <View style={styles.footer}>
          <Text>End of Content</Text>
        </View>
      </ScrollView>
    </KeyboardAvoidingView>
  );
};

// Advanced: Keyboard avoiding with custom insets
const KeyboardAvoidingForm = () => {
  const [keyboardVisible, setKeyboardVisible] = React.useState(false);

  React.useEffect(() => {
    const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
      setKeyboardVisible(true);
    });
    const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
      setKeyboardVisible(false);
    });

    return () => {
      keyboardDidShowListener.remove();
      keyboardDidHideListener.remove();
    };
  }, []);

  return (
    <KeyboardAvoidingView
      behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
      style={styles.formContainer}
      keyboardVerticalOffset={keyboardVisible ? 0 : 100}
    >
      <ScrollView keyboardShouldPersistTaps="handled">
        <Text style={styles.formTitle}>Contact Form</Text>
        {[...Array(8)].map((_, i) => (
          <TextInput
            key={i}
            style={styles.formInput}
            placeholder={`Field ${i + 1}`}
          />
        ))}
        <TouchableOpacity style={styles.formButton}>
          <Text style={styles.formButtonText}>Submit</Text>
        </TouchableOpacity>
      </ScrollView>
    </KeyboardAvoidingView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff'
  },
  scrollContent: {
    padding: 16
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginTop: 20,
    marginBottom: 12
  },
  horizontalScroll: {
    maxHeight: 100
  },
  horizontalContent: {
    gap: 12
  },
  horizontalItem: {
    width: 80,
    height: 80,
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center'
  },
  horizontalText: {
    color: '#fff',
    fontWeight: 'bold',
    fontSize: 18
  },
  nestedContainer: {
    height: 150,
    borderWidth: 1,
    borderColor: '#e0e0e0',
    borderRadius: 8
  },
  nestedScroll: {
    flex: 1
  },
  nestedItem: {
    padding: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#f0f0f0'
  },
  form: {
    gap: 12
  },
  input: {
    borderWidth: 1,
    borderColor: '#e0e0e0',
    borderRadius: 8,
    padding: 12,
    fontSize: 16
  },
  textArea: {
    height: 100,
    textAlignVertical: 'top'
  },
  submitButton: {
    backgroundColor: '#007AFF',
    padding: 16,
    borderRadius: 8,
    alignItems: 'center'
  },
  submitText: {
    color: '#fff',
    fontWeight: '600',
    fontSize: 16
  },
  stickyContainer: {
    maxHeight: 300,
    borderWidth: 1,
    borderColor: '#e0e0e0',
    borderRadius: 8,
    overflow: 'hidden'
  },
  stickyHeader: {
    position: 'sticky',
    top: 0,
    backgroundColor: '#007AFF',
    padding: 12,
    zIndex: 1
  },
  stickyText: {
    color: '#fff',
    fontWeight: 'bold',
    textAlign: 'center'
  },
  stickyItem: {
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#f0f0f0'
  },
  scrollTopButton: {
    marginTop: 20,
    backgroundColor: '#f0f0f0',
    padding: 12,
    borderRadius: 8,
    alignItems: 'center'
  },
  scrollTopText: {
    color: '#007AFF',
    fontWeight: '600'
  },
  footer: {
    marginTop: 20,
    padding: 20,
    alignItems: 'center'
  },
  formContainer: {
    flex: 1,
    backgroundColor: '#fff',
    padding: 16
  },
  formTitle: {
    fontSize: 20,
    fontWeight: 'bold',
    marginBottom: 20
  },
  formInput: {
    borderWidth: 1,
    borderColor: '#e0e0e0',
    borderRadius: 8,
    padding: 12,
    marginBottom: 12,
    fontSize: 16
  },
  formButton: {
    backgroundColor: '#007AFF',
    padding: 16,
    borderRadius: 8,
    alignItems: 'center',
    marginTop: 20
  },
  formButtonText: {
    color: '#fff',
    fontWeight: '600',
    fontSize: 16
  }
});

export default ScrollViewPatterns;

  1. Advanced Layout Techniques

Master advanced layout patterns including masonry grids, circular layouts, and custom measure functions.

React JSXRead-only
1
import React from 'react';
import {
  View,
  Text,
  StyleSheet,
  ScrollView,
  Dimensions,
  Platform
} from 'react-native';

const AdvancedLayouts = () => {
  const { width } = Dimensions.get('window');
  const isTablet = width >= 768;

  // Masonry grid (Pinterest-style)
  const renderMasonryGrid = () => {
    const columnCount = isTablet ? 3 : 2;
    const columnWidth = (width - 48) / columnCount;
    
    // Random heights for masonry effect
    const items = [...Array(12)].map((_, i) => ({
      id: i,
      height: 100 + (i % 5) * 30,
      color: `hsl(${i * 30}, 70%, 60%)`
    }));

    // Distribute items into columns
    const columns = Array(columnCount).fill().map(() => []);
    items.forEach((item, index) => {
      const columnIndex = index % columnCount;
      columns[columnIndex].push(item);
    });

    return (
      <View style={styles.masonryContainer}>
        {columns.map((column, colIndex) => (
          <View key={colIndex} style={[styles.masonryColumn, { width: columnWidth }]}>
            {column.map((item) => (
              <View
                key={item.id}
                style={[
                  styles.masonryItem,
                  {
                    height: item.height,
                    backgroundColor: item.color
                  }
                ]}
              >
                <Text style={styles.masonryText}>{item.id + 1}</Text>
              </View>
            ))}
          </View>
        ))}
      </View>
    );
  };

  // Circular layout
  const renderCircularLayout = () => {
    const centerX = width / 2;
    const centerY = 150;
    const radius = 100;
    const items = 8;

    return (
      <View style={styles.circularContainer}>
        {[...Array(items)].map((_, i) => {
          const angle = (i * 360 / items) * Math.PI / 180;
          const x = centerX + radius * Math.cos(angle) - 20;
          const y = centerY + radius * Math.sin(angle) - 20;
          
          return (
            <View
              key={i}
              style={[
                styles.circularItem,
                {
                  position: 'absolute',
                  left: x,
                  top: y,
                  backgroundColor: `hsl(${i * 45}, 70%, 50%)`
                }
              ]}
            >
              <Text style={styles.circularText}>{i + 1}</Text>
            </View>
          );
        })}
        <View style={[styles.circularCenter, { left: centerX - 30, top: centerY - 30 }]}>
          <Text>Center</Text>
        </View>
      </View>
    );
  };

  // Aspect ratio boxes
  const renderAspectRatioBoxes = () => (
    <View style={styles.aspectContainer}>
      <View style={styles.aspectRow}>
        <View style={[styles.aspectBox, { aspectRatio: 1, backgroundColor: '#FF3B30' }]}>
          <Text>1:1</Text>
        </View>
        <View style={[styles.aspectBox, { aspectRatio: 4/3, backgroundColor: '#FF9500' }]}>
          <Text>4:3</Text>
        </View>
        <View style={[styles.aspectBox, { aspectRatio: 16/9, backgroundColor: '#FFCC00' }]}>
          <Text>16:9</Text>
        </View>
      </View>
      <View style={styles.aspectRow}>
        <View style={[styles.aspectBox, { aspectRatio: 2/1, backgroundColor: '#4CD964' }]}>
          <Text>2:1</Text>
        </View>
        <View style={[styles.aspectBox, { aspectRatio: 3/2, backgroundColor: '#007AFF' }]}>
          <Text>3:2</Text>
        </View>
        <View style={[styles.aspectBox, { aspectRatio: 1/2, backgroundColor: '#5856D6' }]}>
          <Text>1:2</Text>
        </View>
      </View>
    </View>
  );

  // Overlay patterns
  const renderOverlayPatterns = () => (
    <View style={styles.overlayPatterns}>
      {/* Gradient overlay */}
      <View style={styles.overlayExample}>
        <View style={[styles.baseBox, { backgroundColor: '#007AFF' }]} />
        <View style={[styles.overlay, styles.gradientOverlay]}>
          <Text style={styles.overlayWhiteText}>Gradient Overlay</Text>
        </View>
      </View>

      {/* Blur overlay (iOS only) */}
      {Platform.OS === 'ios' && (
        <View style={styles.overlayExample}>
          <View style={[styles.baseBox, { backgroundColor: '#34C759' }]} />
          <View style={[styles.overlay, styles.blurOverlay]}>
            <Text>Blur Effect</Text>
          </View>
        </View>
      )}

      {/* Semi-transparent overlay */}
      <View style={styles.overlayExample}>
        <View style={[styles.baseBox, { backgroundColor: '#FF3B30' }]} />
        <View style={[styles.overlay, styles.semiTransparentOverlay]}>
          <Text style={styles.overlayWhiteText}>Semi-Transparent</Text>
        </View>
      </View>
    </View>
  );

  // Responsive font scaling
  const renderResponsiveText = () => {
    const screenWidth = Dimensions.get('window').width;
    const baseFontSize = screenWidth < 375 ? 14 : screenWidth < 768 ? 16 : 18;

    return (
      <View style={styles.responsiveTextContainer}>
        <Text style={[styles.responsiveTitle, { fontSize: baseFontSize + 6 }]}>
          Responsive Title
        </Text>
        <Text style={[styles.responsiveBody, { fontSize: baseFontSize }]}>
          This text scales based on screen width. On larger screens, it's bigger.
          On smaller screens like iPhone SE, it's more compact.
        </Text>
        <Text style={[styles.responsiveCaption, { fontSize: baseFontSize - 2, color: '#666' }]}>
          Caption text with adaptive sizing
        </Text>
      </View>
    );
  };

  return (
    <ScrollView style={styles.container}>
      <Text style={styles.title}>Advanced Layout Techniques</Text>

      <Text style={styles.sectionTitle}>1. Masonry Grid (Pinterest-style)</Text>
      {renderMasonryGrid()}

      <Text style={styles.sectionTitle}>2. Circular Layout</Text>
      {renderCircularLayout()}

      <Text style={styles.sectionTitle}>3. Aspect Ratio Boxes</Text>
      {renderAspectRatioBoxes()}

      <Text style={styles.sectionTitle}>4. Overlay Patterns</Text>
      {renderOverlayPatterns()}

      <Text style={styles.sectionTitle}>5. Responsive Text Scaling</Text>
      {renderResponsiveText()}

      <View style={styles.tipsCard}>
        <Text style={styles.tipsTitle}>💡 Layout Tips</Text>
        <Text>• Use aspectRatio for consistent image sizing</Text>
        <Text>• Prefer flex over absolute positioning for responsive layouts</Text>
        <Text>• Use Dimensions.addEventListener for orientation changes</Text>
        <Text>• Test on multiple screen sizes (iPhone SE to iPad Pro)</Text>
        <Text>• Use Platform.select for platform-specific layouts</Text>
      </View>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: '#fff'
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginTop: 20,
    marginBottom: 12
  },
  masonryContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between'
  },
  masonryColumn: {
    gap: 12
  },
  masonryItem: {
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center'
  },
  masonryText: {
    color: '#fff',
    fontWeight: 'bold',
    fontSize: 18
  },
  circularContainer: {
    height: 300,
    position: 'relative',
    backgroundColor: '#f0f0f0',
    borderRadius: 12,
    marginBottom: 20
  },
  circularItem: {
    width: 40,
    height: 40,
    borderRadius: 20,
    justifyContent: 'center',
    alignItems: 'center'
  },
  circularText: {
    color: '#fff',
    fontWeight: 'bold'
  },
  circularCenter: {
    width: 60,
    height: 60,
    borderRadius: 30,
    backgroundColor: '#fff',
    position: 'absolute',
    justifyContent: 'center',
    alignItems: 'center',
    borderWidth: 2,
    borderColor: '#007AFF'
  },
  aspectContainer: {
    gap: 12
  },
  aspectRow: {
    flexDirection: 'row',
    gap: 12
  },
  aspectBox: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 8
  },
  overlayPatterns: {
    gap: 12
  },
  overlayExample: {
    position: 'relative',
    height: 100,
    borderRadius: 8,
    overflow: 'hidden'
  },
  baseBox: {
    width: '100%',
    height: '100%'
  },
  overlay: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    justifyContent: 'center',
    alignItems: 'center'
  },
  gradientOverlay: {
    backgroundColor: 'rgba(0,0,0,0.4)'
  },
  blurOverlay: {
    backgroundColor: 'rgba(255,255,255,0.7)'
  },
  semiTransparentOverlay: {
    backgroundColor: 'rgba(0,0,0,0.5)'
  },
  overlayWhiteText: {
    color: '#fff',
    fontWeight: 'bold'
  },
  responsiveTextContainer: {
    backgroundColor: '#f0f0f0',
    padding: 16,
    borderRadius: 8,
    gap: 8
  },
  responsiveTitle: {
    fontWeight: 'bold'
  },
  responsiveBody: {
    lineHeight: 24
  },
  responsiveCaption: {},
  tipsCard: {
    marginTop: 20,
    marginBottom: 40,
    backgroundColor: '#e3f2fd',
    padding: 16,
    borderRadius: 12,
    gap: 8
  },
  tipsTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    marginBottom: 8
  }
});

export default AdvancedLayouts;

Test Your Knowledge

Q1
of 4

What is the default flexDirection in React Native?

A
row
B
column
C
row-reverse
D
column-reverse
Q2
of 4

Which component should you use to handle notches and dynamic islands?

A
View
B
ScrollView
C
SafeAreaView
D
KeyboardAvoidingView
Q3
of 4

What property creates space between children in a flex container?

A
margin
B
padding
C
gap
D
spacing
Q4
of 4

Which value of justifyContent distributes equal space before, between, and after items?

A
space-between
B
space-around
C
space-evenly
D
center

Frequently Asked Questions

What's the difference between flex: 1 and width: '100%'?

flex: 1 fills available space in the flex container based on the flex direction. width: '100%' sets the width to 100% of the parent's width. flex: 1 is more flexible and responsive to parent container changes, while width: '100%' is more explicit. Use flex: 1 for filling remaining space, width: '100%' for exact parent width.

How do I create a sticky header in React Native?

Use position: 'sticky' with top: 0 inside a ScrollView. Note that sticky positioning has limited support on Android (React Native 0.63+). For cross-platform compatibility, consider using third-party libraries like react-native-sticky-header or implement with onScroll event handling.

Why is my absolute positioned element not showing?

Absolute positioned elements are removed from the document flow and may be outside the parent's bounds or hidden by overflow: 'hidden'. Ensure the parent has a defined position (relative), check zIndex values, and verify the element has explicit dimensions (width/height).

How do I handle keyboard avoiding in forms?

Wrap your ScrollView with KeyboardAvoidingView with behavior={Platform.OS === 'ios' ? 'padding' : 'height'}. Add keyboardShouldPersistTaps="handled" to ScrollView. For complex forms, consider react-native-keyboard-aware-scroll-view for more control.

Previous

react native styling

Next

react native navigation

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.